mysql_pconnect() / mysqli::real_connect(..., MYSQLI_CLIENT_PERSISTENT) 將連接放入進程池,下次請求直接復用,省去 TCP 握手、認證、字符集協商開銷。
| 風險 | 現象 | 緩解方案 |
|---|---|---|
| 數據庫重啟/崩潰 | 連接池持有失效句柄,後續請求報 "MySQL server has gone away" | 1. 註冊 mysqli::ping() 健康檢查(每 N 次請求)2. 設置 wait_timeout、interactive_timeout 短於連接池回收週期 |
| Apache 線程耗盡 | MaxClients 已滿,新請求排隊/拒絕 | 1. 調大 MaxClients / ThreadsPerChild2. 監控 show processlist 睡眠連接數,設置 mysql.allow_persistent=Off 禁用 |
| 併發髒讀/事務洩漏 | 請求 A 開啟事務未提交,請求 B 復用同連接看到未提交數據 | 1. 請求結束強制 ROLLBACK / COMMIT2. 關鍵業務禁用永久連接,使用短連接 |
; php.ini
mysql.allow_persistent = On
mysql.max_persistent = -1 ; 無限制,視 Apache 進程數而定
mysql.max_links = -1 ; 總連接數上限
mysqli.allow_persistent = On
mysqli.max_persistent = -1
mysqli.max_links = -1
pdo_mysql.default_socket = /tmp/mysql.sock
function ensureDbAlive(mysqli $mysqli): void {
static $counter = 0;
if (++$counter % 50 === 0) { // 每 50 次請求檢查一次
if (!$mysqli->ping()) {
$mysqli->close();
throw new RuntimeException('DB connection lost, will reconnect next request');
}
}
}
mysqli::real_connect 顯式控制持久標誌,避免隱式行為。