这里我们不考虑 cookie 的过期时间,只考虑与 php 垃圾回收机制有关的问题。需要用到 php.ini 中的下面三个配置项:
- session.gc_maxlifetime
- session.gc_probability
- session.gc_divisor
session.gc_maxlifetime
session.gc_maxlifetime 指定过了多少秒未更新之后数据就会被视为“垃圾”并被清除,默认1440,也就是 24 分钟,如果垃圾收集器启动,会清除 当前时间 - 更新时间 > 1440
的 session 文件。
session的更新时间
下面通过实例来说明 session 何时会更新
// session_test.php
<?php
if ($_GET['type'] == '1') {
session_start();
$_SESSION['first_name'] = 'Andreas';
$_SESSION['last_name'] = 'Wang';
} elseif ($_GET['type'] == '2') {
session_start();
break;
}
- 首先我们模拟登录的情况,先访问 localhost/session.php?type=1,通过调试工具找到 cookie 中 PHPSESSID 的值;

在终端中 cd /private/var/tmp
找到存储 session 文件的目录,通过 stat sess_bidcjuk0uiv3i7rdieo2k6vcbe
查看文件的 modify_time,"modify_time" 就代表这个本条 session 的更新时间
16777220 28699433 -rw------- 1 _www wheel 0 14 "Dec 15 11:03:28 2017" "Dec 15 11:03:28 2017" "Dec 15 11:03:28 2017" "Dec 15 11:03:28 2017" 4096 8 0 sess_bidcjuk0uiv3i7rdieo2k6vcbe
可以看到文件的 modify_time(第二个时间)为 Dec 15 11:03:28 2017,这时我们访问 localhost/session.php?type=2,再执行 stat sess_bidcjuk0uiv3i7rdieo2k6vcbe
,发现 modify_time 改变了。
- 然后删除 cookie,准备测试另一种情况
- 先访问 localhost/session.php?type=2,也就是开启session但不赋值

通过简单的试验,得出结论:
- 当一个 session 中有值时,执行 session_start() ,不管 session 的值有没有修改,这条 session 都已被更新;
- 当 session 中没有值时,如果只执行 session_start() 但不添加 session,session的更新时间不变。
session.gc_probability 和 session.gc_divisor
php并不会在一条session过期后马上清理掉,只有在gc(垃圾回收)进程运行的时候才会找到在那个时间点已过期的session然后进行清理。
session.gc_divisor 和 session.gc_probability 两项配置决定了在每个会话初始化(session_start() )时启动 gc进程的概率,概率为 session.gc_probability / session.gc_divisor
默认 session_start() 每运行100次,gc 才会运行一次,所以默认情况下,只有高访问量的网站才能比较准时地清理过期 session,否则就算session已过期,由于 session_start() 被执行的次数太少,session 也不会被清理。