首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 定時清理 MySQL 睡眠連線:腳本 + Crontab 自動化方案

     編輯:PHP 相關知識

PHP 定時清理 MySQL 睡眠連線:腳本 + Crontab 自動化方案

MySQL 連線池耗盡常見原因:**大量 Sleep 狀態連線佔用**,且 `Time` 值極大(超過 `wait_timeout`/`interactive_timeout` 仍未釋放)。根治需修正應用程式連線洩漏(未正確 `close`、持久連線濫用),但作為緊急緩解與防禦性備援,定時 Kill 長時間 Sleep 連線是實用手段。本文提供 PHP 腳本 + Crontab 部署方案。

殺連線腳本:kill-sleep.php

<?php
/**
 * Kill MySQL 長時間 Sleep 連線
 * 依賴:mysqli 擴充套件
 * 權限:執行帳號需有 PROCESS、SUPER 權限(或至少 KILL 權限)
 */
$dbHost = 'localhost';
$dbUser = 'root';
$dbPass = 'your_password'; // 建議從環境變數/配置檔讀取
$maxSleepTime = 120; // 秒,超過此值視為死連線

$mysqli = new mysqli($dbHost, $dbUser, $dbPass);
if ($mysqli->connect_errno) {
    error_log("[KillSleep] 連線失敗: {$mysqli->connect_error}");
    exit(1);
}

// 查詢進程列表
$sql = "SHOW FULL PROCESSLIST";
$res = $mysqli->query($sql);
if (!$res) {
    error_log("[KillSleep] 查詢失敗: {$mysqli->error}");
    exit(1);
}

$killed = 0;
while ($row = $res->fetch_assoc()) {
    // 僅處理 Sleep 狀態
    if ($row['Command'] === 'Sleep' && $row['Time'] > $maxSleepTime) {
        $id = (int)$row['Id'];
        // 排除自己的連線、複製線程、系統線程
        if ($id === $mysqli->thread_id) continue;

        $killSql = "KILL $id";
        if ($mysqli->query($killSql)) {
            $killed++;
            error_log("[KillSleep] Killed process $id (User: {$row['User']}, Host: {$row['Host']}, DB: {$row['db']}, Time: {$row['Time']}s, Info: {$row['Info']})");
        } else {
            error_log("[KillSleep] Kill $id 失敗: {$mysqli->error}");
        }
    }
}
$res->free();
$mysqli->close();

if ($killed > 0) {
    error_log("[KillSleep] 完成,共清理 $killed 條睡眠連線");
}
?>

部署與自動化

  1. 將腳本放於非 Web 可訪問目錄,如 /usr/local/sbin/kill-sleep.php。
  2. 設定權限:`chmod 700 /usr/local/sbin/kill-sleep.php`,擁有者 `root:root`。
  3. 編輯 Crontab(`crontab -e`):
    # 每 2 分鐘檢查一次
    */2 * * * * /usr/bin/php /usr/local/sbin/kill-sleep.php >> /var/log/kill-sleep.log 2>&1
  4. 驗證日誌:`tail -f /var/log/kill-sleep.log`。

關鍵參數調優建議

參數建議值說明
maxSleepTime120~300 秒視業務長連線特性調整,太短會誤殺正常長輪詢
Crontab 頻率1~5 分鐘頻率過高增加負載,過低清理不及時
MySQL wait_timeout28800 (8小時)預設值,應用層應在遠小於此值時主動釋放
MySQL max_connections1000+配合應用連線池上限設定,避免單點耗盡

根治方案(比 Kill 更重要)

  1. 連線池配置:PHP-FPM + PDO/MySQLi 非持久連線,請求結束自動釋放;Swoole/Workerman 長連線框架需在 `onWorkerStop`/`onClose` 顯式歸還。
  2. 框架層面:Laravel `DB::disconnect()`、ThinkPHP `Db::close()`、Yii `$db->close()`,確保中間件/異常處理流程能執行到。
  3. 監控告警:Prometheus + Grafana 監控 `Threads_connected`、`Aborted_connects`,閾值告警。
  4. 慢查詢分析:長時間 Sleep 可能源自慢查詢阻塞,開啟 `slow_query_log` 定期分析。

延伸閱讀

更多 MySQL 連線池優化、PHP 持久連線陷阱、Swoole 連線管理、Prometheus 監控 MySQL、PT-Kill 工具替代方案、資料庫代理 中間件、連線洩漏排查實戰,請參考本站專題系列。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved