0

我想确切地知道垃圾收集何时运行,所以我制作了下面的测试脚本。

<?php

ini_set('session.gc_maxlifetime',10);
ini_set('session.gc_probability',1);
ini_set('session.gc_divisor',1);

echo ini_get('session.gc_maxlifetime').'s ';
echo ini_get('session.gc_probability').'/';
echo ini_get('session.gc_divisor')."<br>";

session_start();
echo session_id();
if (isset($_SESSION['test']))
{
    echo "<br>";
    echo "session set";
}
$_SESSION['test'] = "works";
echo "<br>";
print_r($_SESSION);

?>

尝试#1:当我第一次尝试时,我得到:

10s 1/1
e9isrrljuvdbr1c6vqndp1e4i7
Array ( [test] => works )

尝试#2:我等待超过 10 秒并得到:

10s 1/1
e9isrrljuvdbr1c6vqndp1e4i7
session set
Array ( [test] => works )

尝试#3:然后我得到:

10s 1/1
e9isrrljuvdbr1c6vqndp1e4i7
Array ( [test] => works )

为什么垃圾收集在尝试 #2 时没有启动,而是在尝试 #3 时启动?

4

1 回答 1

1

会话数据的 PHP 垃圾收集旨在最终清理数据,而不是保证它被清理。

如果您启动会话,PHP 会尝试从上次请求中查找已存储的会话数据。否则,它将假定会话是全新的,在磁盘上创建一个空会话文件,锁定它,并将 $_SESSION 初始化为空数组。

在脚本结束时,或者session_write_close()被调用时,将$_SESSION的内容序列化到这个文件中,释放锁,脚本结束。

只有这样,垃圾收集才会启动,有一定的概率(即 100 个请求中只有一个开始垃圾收集)。它会扫描所有会话文件的过期时间,如果文件的最后修改时间早于session.gc_maxlifetime设置,则将其删除。

其实session.gc_maxlifetime是贴错标签。确实session.gc_minlifetime如此,因为会话数据至少存在这段时间。

第二件事:垃圾收集不能丢弃您正在使用的会话,因为它的数据是新保存的。

第三:垃圾收集需要一个请求来触发它。这不是后台的自动化过程。

将第 2 点和第 3 点结合起来会导致垃圾收集仅清除 OTHER 会话,这些会话的年龄足以比session.gc_maxlifetime. 要对其进行测试,您至少需要两个会话,一个过期,第二个触发执行垃圾回收。

所以它应该是这样的:有两个浏览器,同时访问会话页面。定期在一个浏览器中重新加载页面,在第二个浏览器中等待超过session.gc_maxlifetime几秒钟。只有在第二个浏览器中重新加载 - 会话应该消失。

于 2012-10-24T07:05:12.853 回答