生產環境慢查詢並發可拖垮整個資料庫。本文系統講解 KILL 命令原理、應用層(JDBC)與內核層(AliSQL max_statement_time)自動熔斷機制,並梳理連接/網絡/語句三層 Timeout 參數體系。
一、KILL 命令詳解
KILL [CONNECTION | QUERY] thread_id
KILL QUERY:終止當前語句,連接保持,客戶端收到 ERROR 1317 (70100): Query execution was interrupted。
KILL CONNECTION / KILL thread_id:斷開連接,客戶端收到 ERROR 2013 (HY000): Lost connection to MySQL server during query。
- 權限:
PROCESS 可見所有線程,SUPER 可殺所有線程。
二、KILL 內核實現原理
- 線程標記:
thd->killed = KILL_QUERY / KILL_CONNECTION。
KILL_CONNECTION 直接關閉 socket,立即生效。
KILL_QUERY 依賴關鍵點輪詢 thd->killed:
- SELECT:讀取數據塊後檢查。
- ALTER TABLE:複製數據塊前檢查,終止則刪臨時表。
- UPDATE/DELETE:每讀塊/每行寫入後檢查,非事務表變更不回滾。
- 存儲引擎層:InnoDB
trx_is_interrupted() 統一判斷入口。
三、自動熔斷三大方案對比
| 方案 | 層級 | 原理 | 優點 | 缺點 | 適用場景 |
JDBC Statement.setQueryTimeout(sec) | 驅動/應用 | 客戶端定時器到期發送 KILL QUERY | 無需改造資料庫 | 依賴開發調用、網絡抖動誤殺、佔用客戶端線程 | 快速接入、異構數據庫 |
AliSQL / MySQL 5.7+ max_statement_time | 內核/服務端 | 內部計時器觸發 thd->killed | 統一管控、無網絡開銷、會話/全局級可配 | 需特定版本/內核、不支援預處理語句執行階段超時(部分版本) | 生產級核心業務保護 |
| Proxy 層 | 中間件 | 解析 SQL、註入 Hint/超時控制 | 透明應用、可做熔斷降級 | 引入額外組件、維護成本高 | 分庫分表、多租戶治理 |
四、三層 Timeout 參數體系
| 層級 | 參數 | 單位 | 含義 | 配置建議 |
| 語句執行 | max_statement_time (AliSQL/8.0 max_execution_time) | 毫秒/秒 | 單條 SQL 最大執行時間 | 核心業務 1-5s,報表 30-60s |
| 連接建立 | connectTimeout (JDBC/驅動) | 毫秒 | TCP 三次握手+SSL 握手 | 3-5s,防止掛起佔用連接池 |
| 網絡讀寫 | socketTimeout / readTimeout | 毫秒 | Socket 讀/寫無數據最大等待 | 10-30s,需大於正常慢查詢時間 |
| OS TCP 保活 | tcp_keepalive_time/intvl/probes | 秒 | 內核級死連接檢測 | time=600, intvl=30, probes=3 → 11.5min 檢測死連 |
五、最佳實踐清單
- 資料庫層:啟用
max_statement_time(會話級動態調整),配合慢查詢日誌 long_query_time=1。
- 應用層:強制設置 JDBC
connectTimeout/socketTimeout,使用連接池(HikariCP)預熱與驗證。
- OS 層:調優
tcp_keepalive_* 縮短死連檢測,防止半開連接佔用資源。
- 監控告警:
Threads_running 突增、Slow_queries 突增、Aborted_connects 異常 → 自動觸發 KILL TOP N 慢查詢腳本(pt-kill / 自研)。
- 事務邊界:嚴禁長事務,
autocommit=1 顯式 BEGIN/COMMIT,避免 KILL 導致部分提交不一致。
六、pt-kill 快速上手
# 幹掉運行超過 10 秒的 SELECT
pt-kill --busy-time 10 --match-command Select --kill --print --victims all --interval 1
# 按用戶/庫/表過濾
pt-kill --match-user app_user --match-db app_db --kill