python完成的一個小程式,用于殺掉 mysql 上的異常線程,如慢查詢、處于sleep狀态的。
寫這個腳本的初衷是在使用阿裡雲rds的過程中,資料庫出現異常,需要快速恢複。網上有許多類似的kill腳本,都是通過 mysqladmin 實作的。然而 ali-rds 環境有以下限制:
不提供 super 權限的使用者,也就是使用者隻能 kill 自己的線程
當連接配接數暴增時,外部使用者無法登陸,包括控制台
為了解決上午2大問題,該 python 腳本通過在db執行個體上,使用多線程的方式,為每個使用者保留一個連接配接,并實時讀取指令配置檔案 <code>mysqk.ini</code>,發現有 kill 需求時,利用對應使用者已有連接配接找到 <code>information_schema.processlist</code> 中符合條件的線程,并 kill 。
說明:該腳本在9月份做過一次重寫,7月份的版本(分支 old_0.5.0)是每執行個體每使用者,對應一個線程,db執行個體一多線程數也太多,看得始終不太優雅,于是改成了一個db執行個體一個線程,維護同時維護多個使用者的會話。同時新版也加入了更多的功能,如按時間視窗檢查,包含或排除特定連接配接,郵件通知,配置項覆寫。
始終通過 mysql ping 維持一個長連接配接,并有斷開自動重來機制,解決沒有連接配接可用的尴尬局面
每個db執行個體有自己的線程,避免需要單獨登陸個别使用者去kill的繁複操作。
如果你具有 super 權限,也可以簡化配置做到相容
能夠分開應對需要殺死線程的場景:
長時間運作超過 n 秒的
sleep 狀态的事務 (一般不建議,但有時候kill它,可以快速釋放連接配接給管理者使用)
排除一些線程不能kill,如 binlog dump
包含特定關鍵字的線程要kill
出現符合條件的線程時,會對當時的processlist, engine status,lock_wait 做一個快照,并郵件發出
有試運作dry_run模式,即執行所有的檢查過程但不真正kill
支援隻在時間視窗内運作,考慮到晚上一些長任務不檢查
密碼加密
需要pip安裝<code>mysql-python</code>和<code>pycrypto</code>兩個庫,隻在python 2.7上有測試。
在 settings.py 裡面設定連接配接的使用者名和密碼資訊。這裡假設同一批db的要check的認證資訊是一樣的,指定的使用者既用于登入認證,也用于告知腳本哪些使用者需要被檢查。
密碼要通過 <code>prpcryptec.py</code> 加密,加密的密鑰需寫入腳本本身的 <code>key_db_auth</code>變量。(擔心洩露的話,把mysqk.py編譯成 pyc 來跑)
在 mysqk.ini 主配置檔案裡面
<code>db_info</code> 節設定需要被檢查的資料庫位址,如 <code>db01=10.0.200.100:3306</code>
可分别 <code>db01</code>等指定需要kill thread的選項。<code>[id_db01]</code> 則預設複用 <code>[db_commkill]</code> 的選項
<code>db_comconfig</code> 節設定 <code>db_puser</code> 為能檢視到所有processlist的權限使用者,且在 settings.py 的db_auth中已指定
隻想執行檢查,并不想真正kill異常線程,确認 dry_run不等于0
here we go!
<code>mysqk.ini</code>:
郵件通知相關設定,smtp服務位址和認證資訊。
<code>mail_receiver=</code> 設定空,表示不發郵件
設定要檢查kill哪些資料庫執行個體.
格式:<code><dbid>=<host>:<port></code>,dbid是唯一表示db執行個體的,後面設定各db需要被kill的選項,小節配置名就是 <code>id_<dbid></code>;端口必需指定。
在這裡出現的db執行個體都會被執行檢查,可用 ; 注釋,但需要重新開機腳本。
檢查用公共配置,實時生效。
<code>db_puser</code>:指定一個使用者名用于 show processlist,需要的權限:process、information_schema庫檢視。可以認為是一個代表使用者,檢查異常thread,把結果提供給有該thread殺掉權限使用者。
<code>run_max_count</code>:執行檢查的次數,是一個全局控制開關。每次修改這個值都會重新開始檢查,即一個 clean start,讓剛修改的配置生效。
為 0 表示腳本不進行任何檢查,隻簡單維護與資料庫的連接配接存活。存活檢查頻率在 settings.py 由 <code>check_config_interval × check_ping_multi</code>決定
為 999 表示會在背景一緻檢查連接配接線程(但不一定有符合kill條件的),檢查的頻率在 settings.py 裡面 <code>check_config_interval</code> 指定
為其它值時,表示檢查次數滿後停止檢查
<code>dry_run</code>:是否開啟試運作模式,為0表示真實kill,為1或其它值表示試運作。試運作模式可用于監控慢查詢并告警。注意同一會話線程id隻告警一次
<code>run_time_window</code>:運作的檢查的時間視窗,格式如 <code>08:00-22:00</code>,在這個時間以外不執行檢查,留白表示不限制。主要考慮晚上一些統計任務可能出現“異常”線程。
kill用公共配置,實時生效,會被 <code>id_<dbid></code> 節的選項覆寫。
<code>k_user</code>:很關鍵的一個選項,表示你要檢查并kill哪些資料庫使用者,多個用逗号分隔(不要帶引号)。
為 <code>all</code> 時,表示要檢查 settings.py 裡 db_auth 指定的所有使用者
為 <code>none</code> 時,表示不kill任何異常線程,效果與設定了 dry_run 模式相當
<code>k_longtime</code>:執行超過設定值的sql則認為異常。一般大于 check_config_interval
<code>k_sleep</code>:sleep超過設定秒的sql則認為異常,為 0 表示不殺掉sleep狀态的線程
<code>k_exclude</code>:排除掉那些特定關鍵字的線程,比如複制線程、管理者的連接配接等
<code>k_include</code>:包含這些特定關鍵字的線程,需要被kill。注意,它作用在滿足 k_user 和 k_exclude 的前提之下。
k_exclude與k_include 的值是支援python re子產品正則的格式,不要帶引号
這部分區域的配置項與 db_commconfig 相同,用于針對個别db的kill選項。
兩種組合模式:
設定 <code>dry_run=0</code>,預設 <code>k_user=none</code>,當資料庫出現異常時,主動修改對應db的k_user值,動态kill
設定 <code>dry_run=1</code>,預設 <code>k_user=all</code>,相當于運作在daemon模式,有慢查詢則郵件通知,并且記錄下當時的資訊
當然你也可以<code>dry_run=0</code>,<code>k_user=all</code>,讓程式一直在背景跑并kill,但生産環境極不推薦。
有日志和快照檔案可以檢視。
mysqlk.ini :