2012-10-24 46 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表明這不是真的。 –