PHPSESSID)session_start() 從存儲介質加載數據填充 $_SESSIONsession_register() / 直接操作 $_SESSION 註冊變量session.save_path 控制)| 方案 | 優點 | 缺點 |
|---|---|---|
| 文件分層目錄 | 實現簡單 | I/O 瓶頸無法根治,inode 耗盡風險 |
| MySQL 數據庫 | 持久化、支持集群、便於查詢審計、跨節點共享 | 寫入延遲略高於內存 |
| Redis/Memcached | 極高性能、原生 TTL、集群擴展性強 | 需額外運維組件、數據持久化風險 |
本文採用折中方案:Session 入 MySQL,兼顧共享與運維簡單度。
CREATE TABLE `session` ( `session_id` VARCHAR(128) NOT NULL PRIMARY KEY, `session_data` TEXT NOT NULL, `session_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

通過 session_set_save_handler() 註冊六個回調函數:
ini_set("session.save_handler", "user");
ini_set("session.gc_probability", 1);
ini_set("session.gc_divisor", 2); // 50% 概率觸發 GC
ini_set("session.gc_maxlifetime", 1440); // 24 分鐘過期
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
session_data,返回序列化字符串(空串表示無數據),PHP 自動反序列化填充 $_SESSIONINSERT ... ON DUPLICATE KEY UPDATE 寫入/更新,session_time 用於 GC 判斷DELETE 對應記錄,session_destroy() 或 session_regenerate_id(true) 觸發DELETE WHERE NOW() - session_time > maxlifetime,概率觸發完整代碼見原文,關鍵注意:
mysql_connect 而非 PDO/mysqli(舊版本兼容),生產建議升級write 回調在輸出流關閉後執行,調試輸出需寫文件session.serialize_handler 一致(默認 php,非 serialize())session_start() → 讀 Cookie PHPSESSIDread() 獲取數據 → 反序列化 → 填充 $_SESSION$_SESSION(純內存操作)session_destroy() → 調用 write() 持久化session_destroy() → 調用 destroy() 刪除記錄 → 不再 write()write 推入消息隊列,後台異步落庫,降低請求延遲session_data 較大時考慮 gzcompress