最近項目中的數據庫查詢常常掛起,應用程序啓動後也報操做超時。測試人員就說數據庫又掛了(貌似他們眼中的鏈接失敗,查詢無果都是掛了),經過 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
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。數據庫
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