Python完成的一個小程序,用於殺掉 MySQL 上的異常線程,如慢查詢、處於Sleep狀態的。
項目地址:https://github.com/seanlook/m... python
寫這個腳本的初衷是在使用阿里雲RDS的過程當中,數據庫出現異常,須要快速恢復。網上有許多相似的kill腳本,都是經過 mysqladmin 實現的。然而 Ali-RDS 環境有如下限制:mysql
不提供 SUPER 權限的用戶,也就是用戶只能 kill 本身的線程git
當鏈接數暴增時,外部用戶沒法登錄,包括控制檯github
爲了解決上午2大問題,該 python 腳本經過在db實例上,使用多線程的方式,爲每一個用戶保留一個鏈接,並實時讀取指令配置文件 mysqk.ini
,發現有 kill 需求時,利用對應用戶已有鏈接找到 information_schema.processlist
中符合條件的線程,並 kill 。sql
說明:該腳本在9月份作過一次重寫,7月份的版本(分支 old_0.5.0)是每實例每用戶,對應一個線程,db實例一多線程數也太多,看得始終不太優雅,因而改爲了一個db實例一個線程,維護同時維護多個用戶的會話。同時新版也加入了更多的功能,如按時間窗口檢查,包含或排除特定鏈接,郵件通知,配置項覆蓋。數據庫
始終經過 mysql ping 維持一個長鏈接,並有斷開自動重來機制,解決沒有鏈接可用的尷尬局面小程序
每一個db實例有本身的線程,避免須要單獨登錄個別用戶去kill的繁複操做。
若是你具備 SUPER 權限,也能夠簡化配置作到兼容多線程
可以分開應對須要殺死線程的場景:測試
長時間運行超過 N 秒的this
Sleep 狀態的事務 (通常不建議,但有時候kill它,能夠快速釋放鏈接給管理員使用)
排除一些線程不能kill,如 Binlog dump
包含特定關鍵字的線程要kill
出現符合條件的線程時,會對當時的processlist, engine status,lock_wait 作一個快照,並郵件發出
有試運行dry_run模式,即執行全部的檢查過程但不真正kill
支持只在時間窗口內運行,考慮到晚上一些長任務不檢查
密碼加密
<!-- more -->
須要pip安裝MySQL-python
和pycrypto
兩個庫,只在python 2.7上有測試。
在 settings.py 裏面設置鏈接的用戶名和密碼信息。這裏假設同一批db的要check的認證信息是同樣的,指定的用戶既用於登陸認證,也用於告知腳本哪些用戶須要被檢查。
密碼要經過 prpcryptec.py
加密,加密的密鑰需寫入腳本自己的 KEY_DB_AUTH
變量。(擔憂泄露的話,把mysqk.py編譯成 pyc 來跑)
在 mysqk.ini 主配置文件裏面
db_info
節設置須要被檢查的數據庫地址,如 db01=10.0.200.100:3306
可分別 db01
等指定須要kill thread的選項。[id_db01]
則默認複用 [db_commkill]
的選項
db_comconfig
節設置 db_puser
爲能查看到全部processlist的權限用戶,且在 settings.py 的DB_AUTH中已指定
只想執行檢查,並不想真正kill異常線程,確認 dry_run不等於0
Here we go!
mysqk.ini
:
郵件通知相關設置,smtp服務地址和認證信息。mail_receiver=
設置空,表示不發郵件
設置要檢查kill哪些數據庫實例.
格式:<dbid>=<host>:<port>
,dbid是惟一表示db實例的,後面設置各db須要被kill的選項,小節配置名就是 id_<dbid>
;端口必需指定。
在這裏出現的db實例都會被執行檢查,可用 ; 註釋,但須要重啓腳本。
檢查用公共配置,實時生效。
db_puser
:指定一個用戶名用於 show processlist,須要的權限:PROCESS、information_schema庫查看。能夠認爲是一個表明用戶,檢查異常thread,把結果提供給有該thread殺掉權限用戶。
run_max_count
:執行檢查的次數,是一個全局控制開關。每次修改這個值都會從新開始檢查,即一個 clean start,讓剛修改的配置生效。
爲 0 表示腳本不進行任何檢查,只簡單維護與數據庫的鏈接存活。存活檢查頻率在 settings.py 由 CHECK_CONFIG_INTERVAL × CHECK_PING_MULTI
決定
爲 999 表示會在後臺一致檢查鏈接線程(但不必定有符合kill條件的),檢查的頻率在 settings.py 裏面 CHECK_CONFIG_INTERVAL
指定
爲其它值時,表示檢查次數滿後中止檢查
dry_run
:是否開啓試運行模式,爲0表示真實kill,爲1或其它值表示試運行。試運行模式可用於監控慢查詢並告警。注意同一會話線程ID只告警一次
run_time_window
:運行的檢查的時間窗口,格式如 08:00-22:00
,在這個時間之外不執行檢查,留空表示不限制。主要考慮晚上一些統計任務可能出現「異常」線程。
kill用公共配置,實時生效,會被 id_<dbid>
節的選項覆蓋。
k_user
:很關鍵的一個選項,表示你要檢查並kill哪些數據庫用戶,多個用逗號分隔(不要帶引號)。
爲 all
時,表示要檢查 settings.py 裏 DB_AUTH 指定的全部用戶
爲 none
時,表示不kill任何異常線程,效果與設置了 dry_run 模式至關
k_longtime
:執行超過設定值的sql則認爲異常。通常大於 CHECK_CONFIG_INTERVAL
k_sleep
:Sleep超過設定秒的sql則認爲異常,爲 0 表示不殺掉sleep狀態的線程
k_exclude
:排除掉那些特定關鍵字的線程,好比複製線程、管理員的鏈接等
k_include
:包含這些特定關鍵字的線程,須要被kill。注意,它做用在知足 k_user 和 k_exclude 的前提之下。
k_exclude與k_include 的值是支持python re模塊正則的格式,不要帶引號
這部分區域的配置項與 db_commconfig 相同,用於針對個別db的kill選項。
兩種組合模式:
設置 dry_run=0
,默認 k_user=none
,當數據庫出現異常時,主動修改對應db的k_user值,動態kill
設置 dry_run=1
,默認 k_user=all
,至關於運行在daemon模式,有慢查詢則郵件通知,而且記錄下當時的信息
固然你也能夠dry_run=0
,k_user=all
,讓程序一直在後臺跑並kill,但生產環境極不推薦。
有日誌和快照文件能夠查看。
mysqlk.ini :
[mail_config] mail_host=smtp.exmail.qq.com mail_user=xxx@ecqun.com mail_pass=xxxxxx mail_receiver= [db_info] crm0=192.168.1.125:3306 crm1=192.168.1.126:3306 crm2=192.168.1.127:3306 crm3=192.168.1.128:3306 base=10.0.200.142:3306 [db_commconfig] db_puser=ecuser ; how many kill times once this config file changed ; 0: DISABLE all kill ; 999: always kill threads that meet kill conditions ; default: 1 ; can not be inherit run_max_count=999 dry_run=1 run_time_window=08:00-22:00 [db_commkill] k_user=all k_longtime=10 k_lock=1 k_sleep=0 k_exclude=Binlog|ecdba|Daemon k_include=select sleep\(17\) [id_crm0] ; k_user: who's threads to be killed. use comma to separate ; none: do not kill anyone's threads ; all: kill all user's threads (with other where conditions) ; default: none k_user=all ; k_longtime: filter the threads who's running time is longer than this ; 0: ignore the time > x condition ; default: 10 k_longtime=10 ; k_sleep: whether kill sleepd threads or not ; 0: do not kill command='Sleep' threads from processlist ; when it set to 1, usually it's subset of k_longtime condition ; default: 0 k_sleep=0 [id_crm1] k_user=ecuser k_longtime=10 k_sleep=0 [id_crm2] k_user=all k_longtime=10 k_sleep=0 [id_crm3]