預設 PHP Session 資料儲存在伺服器檔案系統中,但在分散式架構或負載平衡環境下,需將 Session 集中儲存於資料庫以實現共享。本文示範如何使用 session_set_save_handler() 自訂 Session 儲存機制,搭配 MySQL 資料表實作完整的讀寫、銷毀與垃圾回收流程。
建立 sessions 資料表,主鍵為 session_id,包含過期時間與序列化資料欄位:
CREATE TABLE `sessions` ( `session_id` varchar(255) NOT NULL, `session_expires` int(11) DEFAULT NULL, `session_data` text, PRIMARY KEY (`session_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
實作 SessionHandlerInterface 介面所需的六個方法:open、close、read、write、destroy、gc。以下為核心程式碼架構(已移除舊版 mysql_* 函數,建議實際專案改用 PDO 或 MySQLi):
<?php
class SessionHandler {
private $lifeTime;
private $dbHandle;
public function open($savePath, $sessName) {
$this->lifeTime = ini_get('session.gc_maxlifetime');
// 建議使用 PDO 連線
$this->dbHandle = new PDO('mysql:host=localhost;dbname=mysession', 'root', 'root');
return true;
}
public function close() {
$this->gc(ini_get('session.gc_maxlifetime'));
$this->dbHandle = null;
return true;
}
public function read($sessID) {
$stmt = $this->dbHandle->prepare('SELECT session_data FROM sessions WHERE session_id = ? AND session_expires > ?');
$stmt->execute([$sessID, time()]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? $row['session_data'] : '';
}
public function write($sessID, $sessData) {
$newExp = time() + $this->lifeTime;
$stmt = $this->dbHandle->prepare('REPLACE INTO sessions (session_id, session_expires, session_data) VALUES (?, ?, ?)');
return $stmt->execute([$sessID, $newExp, $sessData]);
}
public function destroy($sessID) {
$stmt = $this->dbHandle->prepare('DELETE FROM sessions WHERE session_id = ?');
return $stmt->execute([$sessID]);
}
public function gc($maxLifeTime) {
$stmt = $this->dbHandle->prepare('DELETE FROM sessions WHERE session_expires < ?');
$stmt->execute([time()]);
return $stmt->rowCount();
}
}
// 註冊處理器並啟動 Session
$handler = new SessionHandler();
session_set_save_handler($handler, true);
session_start();
// 測試寫入資料
$_SESSION['user'] = ['name' => 'gxx', 'pass' => '123'];
?>
session_id 查詢有效資料,若過期則回傳空字串觸發新 Session。REPLACE INTO 同時處理新增與更新,避免競態條件。TEXT 或 LONGTEXT。session.use_strict_mode 並設定適當的 session.gc_probability。透過資料庫儲存 Session,可輕鬆支援多伺服器叢集架構,是打造高可用性 PHP 應用的關鍵技術之一。