記一次MySQL中Waiting for table metadata lock問題的處理

原由:因爲須要,要把一張表的一個字段從不是 null 改爲 可null,我用的Navicat Premium ,可是在保存的時候,工具無響應了,幾個同事操做都是這樣的,很奇怪,懷疑是否是因爲表被鎖了仍是什麼緣由html

 

去數據庫看下:mysql

show processlist;

發現有一個線程很奇怪:這個進程的State是Waiting for table metadata lock ,Info是alter table bus_order modify...  而且Time已經800多秒了

能肯定這就是剛纔修改字段屬性的保存操做,可是爲何卡死了呢,Google了下Waiting for table metadata lock發現緣由了:

原來是有操做這張表的未提交事務,在事務沒有完成以前,這個表上的鎖不會釋放,alter table一樣獲取不到metadata的獨佔鎖
sql

經過下面兩個語句,定位到操做該表的未提交事務:數據庫

1 select t.trx_mysql_thread_id from information_schema.innodb_trx t;
2 show processlist;

而後kill掉這個線程,再保存,馬上保存成功了。session

結論&拓展:工具

  • 情景1:一個較耗時的事務運行的時候,這時進行alter table,就會阻塞DDL,繼而阻塞全部當前表的後續操做

    經過show processlist能夠看到所操做表上有正在進行的操做(包括讀),此時alter table語句沒法獲取到metadata 獨佔鎖,會進行等待。ui

    這是最基本的一種情形,這個和mysql 5.6中的online DLL並不衝突。通常alter table的操做過程當中,在after create步驟會獲取metadata 獨佔鎖,當進行到altering table的過程時(一般是最花時間的步驟),對該表的讀寫均可以正常進行,這就是online ddl的表現,並不會像以前在整個alter table過程當中阻塞寫入。(固然,也並非全部類型的alter操做都能online的,具體能夠參見官方手冊:http://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html
    處理方法: kill 掉 DDL所在的session.spa

  • 情景2:存在未提交事務,阻塞DDL,繼而阻塞全部同表的後續操做
    經過show processlist看不到TableA上有任何操做,但實際上存在有未提交的事務,能夠經過下面的命令查看未提交的事務:
    select t.trx_mysql_thread_id from information_schema.innodb_trx t

    在事務沒有完成以前,Table上的鎖不會釋放,alter table一樣獲取不到metadata的獨佔鎖線程

    處理方法:經過上面的命令找到未提交的事務,而後 kill 掉,讓其回滾。
  • 場景3:

    經過show processlist看不到TableA上有任何操做,在information_schema.innodb_trx中也沒有任何進行中的事務。這極可能是由於在一個顯式的事務中,對TableA進行了一個失敗的操做(好比查詢了一個不存在的字段),這時事務沒有開始,可是失敗語句獲取到的鎖依然有效,沒有釋放。從performance_schema.events_statements_current表中能夠查到失敗的語句。日誌

    官方手冊上對此的說明以下:

    If the server acquires metadata locks for a statement that is syntactically valid but fails during execution, it does not release the locks early. Lock release is still deferred to the end of the transaction because the failed statement is written to the binary log and the locks protect log consistency.

    也就是說除了語法錯誤,其餘錯誤語句獲取到的鎖在這個事務提交或回滾以前,仍然不會釋放掉。because the failed statement is written to the binary log and the locks protect log consistency 可是解釋這一行爲的緣由很難理解,由於錯誤的語句根本不會被記錄到二進制日誌。

    處理方法:經過performance_schema.events_statements_current找到其sid, kill 掉該session. 也能夠 kill 掉DDL所在的session.

總之,alter table的語句是很危險的(其實他的危險實際上是未提交事物或者長事務致使的),在操做以前最好確認對要操做的表沒有任何進行中的操做、沒有未提交事務、也沒有顯式事務中的報錯語句。若是有alter table的維護任務,在無人監管的時候運行,最好經過lock_wait_timeout設置好超時時間,避免長時間的metedata鎖等待。

相關文章
相關標籤/搜索