mysql中kill掉全部鎖表的進程

最近項目中的數據庫查詢常常掛起,應用程序啓動後也報操做超時。測試人員就說數據庫又掛了(貌似他們眼中的鏈接失敗,查詢無果都是掛了),經過 show processlist 一看,滿屏都是 Waiting for table metadata lock 狀態的鏈接。第一反應就是kill掉這些鏈接,奈何鏈接實在太多,實在kill不過來,因而重啓服務,貌似重啓果然能解決90%的問題,但若是不找到問題緣由,問題也確定會再次出現。html

在網上查詢得知MySQL在進行一些alter table等DDL操做時,若是該表上有未提交的事務則會出現 Waiting for table metadata lock ,而一旦出現metadata lock,該表上的後續操做都會被阻塞(詳見 http://www.bubuko.com/infodetail-1151112.html)。因此這個問題需從兩方面解決mysql

  1. 查看未提交事務
    從 information_schema.innodb_trx 表中查看當前未提交的事務
select trx_state, trx_started, trx_mysql_thread_id, trx_query from information_schema.innodb_trx\G

(\G做爲結束符時,MySQL Client會把結果以列模式展現,對於列比較長的表,展現更直觀)sql

字段意義:shell

trx_state: 事務狀態,通常爲RUNNING
trx_started: 事務執行的起始時間,若時間較長,則要分析該事務是否合理
trx_mysql_thread_id: MySQL的線程ID,用於kill
trx_query: 事務中的sql
通常只要kill掉這些線程,DDL操做就不會Waiting for table metadata lock。數據庫

  1. 調整鎖超時閾值
    lock_wait_timeout 表示獲取metadata lock的超時(單位爲秒),容許的值範圍爲1到31536000(1年)。 默認值爲31536000。詳見 https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_lock_wait_timeout 。默認值爲一年!!!已哭瞎!將其調整爲30分鐘
set session lock_wait_timeout = 1800;
set global lock_wait_timeout = 1800;

好讓出現該問題時快速故障(failfast)bash

kill掉第一個鎖表的進程, 依然沒有改善. 既然不改善, 我們就想辦法將全部鎖表的進程kill掉吧, 簡單的腳本以下.session

#!/bin/bash
mysql -u root -e "show processlist" | grep -i "Locked" >> locked_log.txt

for line in `cat locked_log.txt | awk '{print $1}'`
do 
   echo "kill $line;" >> kill_thread_id.sql
done

如今kill_thread_id.sql的內容像這個樣子ide

kill 66402982;
kill 66402983;
kill 66402986;
kill 66402991;
.....

好了, 咱們在mysql的shell中執行, 就能夠把全部鎖表的進程殺死了.測試

mysql>source kill_thread_id.sql線程

固然了, 也能夠一行搞定

for id in `mysqladmin processlist | grep -i locked | awk '{print $1}'`
do
   mysqladmin kill ${id}
done
相關文章
相關標籤/搜索