phpBB3 引發的 MySQL slow query (2) -- 修改方案
發表於 : 2025-08-06, 20:32
修改 phpbb/sessions.php
修改 function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
在function session_create(...)其後加入清理和重整的機制,放在開頭處容易識別
若使用 OPTIMIZE 或 ALTER 等相關指令會有卡住的風險,運行慢一點,無妨.
成效需要驗證.
目前終於把無效的匿名 session 減至 20,000 以下.
註: 去掉 ORDER BY session_time 以加速運行
(待修)
修改 function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
在function session_create(...)其後加入清理和重整的機制,放在開頭處容易識別
若使用 OPTIMIZE 或 ALTER 等相關指令會有卡住的風險,運行慢一點,無妨.
代碼: 選擇全部
// +++ InnoDB 優化清理 +++
$sql = 'SELECT COUNT(session_id) AS sessions
FROM ' . SESSIONS_TABLE . '
WHERE session_time >= ' . ($this->time_now - 60);
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$life_sessions = $row ? (int)$row['sessions'] : 0; //合理連線數
$multi_sessions = 5; //合理連線數保留的倍數
$max_sessions = 10000; // 清理的閾值
// 使用快速估算方法
// 替代 information_schema 的輕量計數
$result = $db->sql_query("SELECT COUNT(*) AS session_count FROM ".SESSIONS_TABLE);
$row = $db->sql_fetchrow($result);
$session_count = $row ? (int)$row['session_count'] : 0;
//超過預設閾值且超過保留數量的匿名資料
if ($session_count > $max_sessions and $session_count > $life_sessions * $multi_sessions) {
// 保留30分鐘 (不可以使用 now() 要使用 $this->time_now 以計算時間)
$cutoff = $this->time_now - 1800;
$batch = 5000; // 每批刪除上限
$total = 0;
do {
// 可選:把本連線的鎖等待時間壓低,避免卡太久
$db->sql_query('SET SESSION innodb_lock_wait_timeout = 3');
$sql = 'DELETE FROM ' . SESSIONS_TABLE . '
WHERE session_user_id = ' . (int) ANONYMOUS . '
AND session_time <= ' . (int) $cutoff . '
LIMIT ' . (int) $batch;
$db->sql_query($sql);
$affected = $db->sql_affectedrows();
$total += $affected;
// 每批删除后暂停
if ($affected > 0)
usleep(100000); // 100ms 暂停
} while ($affected === $batch);
// 分批刪除結束
}
// --- 優化結束 ---
目前終於把無效的匿名 session 減至 20,000 以下.
註: 去掉 ORDER BY session_time 以加速運行
(待修)