我想确切地知道垃圾收集何时运行,所以我在下面制作了测试脚本。
<?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?
答案 0 :(得分:1)
会话数据的PHP垃圾收集旨在最终清理数据,而不是保证它被清除。
如果启动会话,PHP会尝试从上次请求中查找已存储的会话数据。如果做不到这一点,它将假设会话是全新的,在磁盘上创建一个空的会话文件,将其锁定,并将$ _SESSION初始化为空数组。
在脚本结束时,或者在调用session_write_close()
时,$ _SESSION的内容被序列化到此文件,锁被释放,脚本结束。
只有这时垃圾收集才有可能(即100个请求中只有一个启动垃圾收集)。它扫描所有会话文件是否到期,如果文件的上次修改时间早于session.gc_maxlifetime
设置,则会被删除。
事实上,session.gc_maxlifetime
被贴错了标签。它确实是session.gc_minlifetime
,因为会话数据至少存在这段时间。
第二件事:垃圾收集不能丢弃您正在使用的会话,因为它的数据是刚刚保存的。
第三:垃圾收集需要触发它的请求。它不是后台的自动化过程。
将第二点和第三点结合起来会导致垃圾收集清理仅清除那些年龄足够大于session.gc_maxlifetime
的其他会话。要测试它,你需要至少两个会话,一个到期,第二个触发执行垃圾收集。
所以它应该是这样的:有两个浏览器,用两者访问会话页面。定期在一个浏览器中重新加载页面,在第二个浏览器中等待超过session.gc_maxlifetime
秒。只有在第二个浏览器中重新加载 - 会话才会消失。