2012-10-24 50 views
0

我想知道垃圾收集何时会运行,所以我在下面做了测试脚本。PHP垃圾收集在后期启动

<?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) 

为什么垃圾col尝试#2没有踢,但尝试#3踢?

+0

好像'在session_start()'读会话,并运行GC – zerkms

+0

后,才从文档'垃圾收集会话启动过程中可能出现...'为什么它看完后删除会议?这将是疯狂的,虽然它看起来就是它实际上在做的。 –

+0

最精确的答案可以给一些对PHP源码足够自信的人。我们只能猜测:-) – zerkms

回答

1

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

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

在脚本末尾或调用session_write_close()时,$ _SESSION的内容被序列化为该文件,锁定被释放,脚本结束。

只有当垃圾收集以概率(即100个请求中只有一个开始垃圾收集)进行时才会启动。它会扫描所有会话文件的过期时间,如果上次修改文件的时间早于session.gc_maxlifetime设置,则会被删除。

实际上,session.gc_maxlifetime被误标。它确实是session.gc_minlifetime,因为会话数据至少占用了这段时间。

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

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

将第二点和第三点结合起来会导致垃圾收集只会清除其他年龄大于session.gc_maxlifetime的会话。为了测试它,您至少需要两个会话,一个会到期,另一个会触发执行垃圾回收。

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

+0

session.gc_minlifetime确实更有意义。但是文档说'垃圾收集可能会在会话开始时发生(取决于session.gc_probability和session.gc_divisor)。“但上面声称垃圾收集发生在脚本的末尾。你也声称一个会话不能触发它自己的垃圾收集,但是尝试#3表明这不是真的。 –