在生產環境中開啟 PHP-FPM 慢速日誌(request_slowlog_timeout)是效能調優的常規手段,但某些情況下卻可能觸發 Lost connection to MySQL server during query (錯誤碼 2013) 的離奇故障。本文記錄一次真實排查過程,揭示慢速日誌與資料庫連線中斷的隱性關聯。
request_slowlog_timeout = 10smysql_ping() 重連檢查無法解決抱著「死馬當活馬醫」心態關閉 PHP 慢速日誌後,問題瞬間消失。這表明慢速日誌機制本身干擾了長時間執行的資料庫操作。
當請求執行超過閾值,PHP-FPM 主進程會發送 SIGALRM 信號給工作進程,強制中斷當前執行並導出堆疊追蹤。此過程具有非同步中斷特性:
mysql_query() 等阻塞式系統呼叫// 典型的重連檢查邏輯
if (!mysql_ping($link)) {
$link = mysqli_connect(...); // 重新連線
}
mysqli_query($link, $sql);
mysql_ping() 僅檢查連線是否存活,但無法預測「下一條 SQL 執行期間」是否會再次被慢速日誌中斷。迴圈中每次查詢約 12 秒,遠超 10 秒閾值,導致每次查詢都會被中斷一次,連線狀態處於持續不穩定狀態。
MySQL 協定要求命令/回應嚴格配對。慢速日誌中斷導致:
SIGALRMwait_timeout 或 net_read_timeout)將閾值設為業務允許的最大執行時間 2 倍以上:
; php-fpm.conf
request_slowlog_timeout = 30s ; 批次任務建議 30-60 秒
request_slowlog_trace_depth = 20
php script.php),完全繞過 PHP-FPM 慢速日誌pcntl_signal 自行處理超時邏輯INSERT ... VALUES (...), (...) 或預處理語句)$mysqli = new mysqli(...);
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
$mysqli->options(MYSQLI_OPT_READ_TIMEOUT, 30); // PHP 7.2+ 支援
$mysqli->options(MYSQLI_OPT_WRITE_TIMEOUT, 30);
| 誤區 | 正確認知 |
|---|---|
| 慢速日誌只記錄不影響執行 | 會發送 SIGALRM 中斷執行流,影響阻塞式 I/O |
| mysql_ping 可解決所有斷線 | 無法防禦「執行期間被中斷」導致的協定錯亂 |
| 所有慢查詢都應記錄 | 批次/排程任務應移至 CLI 或調高閾值 |
結論:PHP 慢速日誌是雙面刃,長時間資料庫操作場景下需謹慎配置閾值,或將此類任務遷移至 CLI 環境執行,從根源避免信號中斷干擾 MySQL 協定交互。