1. 程式人生 > >一次Waiting for table metadata lock的處理

一次Waiting for table metadata lock的處理

檢視鎖表的程序:
1、查程序,查詢被鎖表的那個程序的ID

show processlist;

2、kill掉鎖表的程序ID

kill id;

3、查詢是否鎖表

show OPEN TABLES where In_use > 0;

解決過程:

版本:mysql5.5.17

檢視:Innodb_buffer_pool_pages_free = 0

解決:set global innodb_stats_on_metadata=0

原因詳解

一個沒提交的事務使用了A表, 另外一個session 對A表進行alter,出現waiting for table metadata lock

在insert into t select * from share 執行時, 同時執行alter table t add index(play_count),
alter table語句會Waiting for table metadata lock, 直到insert into … select 語句結束。

不是傳說5.6支援online DDL麼? 怎麼還會Waiting for table metadata lock?
後來想想, online DDL應該是指在alter table進行的時候, 插入/修改/刪除資料的sql語句不會Waiting for table metadata lock. (ps:順序不一樣)

參考:http://www.cnblogs.com/dyllove98/archive/2013/07/16/3194332.html

版本:mysql5.5.17

檢視:Innodb_buffer_pool_pages_free = 0

解決:set global innodb_stats_on_metadata=0

檢視丁奇老大部落格:原文http://dinglin.iteye.com/blog/1575840

這個問題來自冷之同學測試時候碰到的一個“詭異現象”。

1、 測試現象

測試的庫有很多資料,但是重啟之後,只對一個表的5w條記錄作查詢。查詢條件客戶端控制,確保查詢範圍。innodb_buffer_pool_size設定為35G。

現象1:查詢效能會出現大幅度抖動;

現象2:介入追查後發現,Innodb_buffer_pool_pages_free = 0

     其中bp剩餘量這個是最直觀異常的,因為訪問的5w行記錄撐死也不可能把35G記憶體吃光的。在QA同學確認沒有別人在使用這個庫的情況下。 

2、過程和原因

     其實幾乎確定還是有別的查詢在訪問的。所以開啟general_log。 發現除了QA同學壓的語句外,這個Server上還有一些監控語句。 

     其中一個語句如下 

select constraint_schema,table_name,constraint_name,constraint_type from information_schema.table_constraints where table_schema not in (‘information_schema’, ‘mysql’, ‘test’);

     這個語句訪問了表 information_schema.table_constraints. 

跟蹤發現這個語句觸發了讀盤操作。原因是需要訪問引擎的info()介面,而InnoDB此時又“順手”做了更新索引統計的操作dict_update_statistics。

更新索引統計的基本流程是隨機讀取部分demo行。所以這個操作實際上是訪問了這個Server裡面的所有表,因此不只是訪問5w行。

而且由於別的表事先沒有被訪問,就會導致讀盤操作,也包括BP的LRU更新。

3、哪些表會觸發

     不只是上面提到的table_constraints,information_schema庫下的一下幾個表,訪問時候都會觸發這個“順手”操作。 

information_schema.TABLES

information_schema.STATISTICS

information_schema.PARTITIONS

information_schema.KEY_COLUMN_USAGE

information_schema.TABLE_CONSTRAINTS

information_schema.REFERENTIAL_CONSTRAINTS

     其實還有 show table status ,也會觸發這個操作,只是只處理單表,所以影響沒那麼明顯。 

4、修改

頭痛醫頭的方法是把這些監控去掉。但實際上像TABLES、TABLE_CONSTRAINTS這些表,都是靜態資料,訪問時不作索引統計也沒關係的。

另外一個方法就是把innodb_stats_on_metadata設定成off,這樣上述說到的這些表訪問都不會觸發索引統計。

     實際上這個動態統計的功能已經不推薦了,官方已經在6.0以後增加引數控制DML期間也不作動態統計了。因此這個引數配置成off更合理些(預設是on)

本文轉載自ITEYE文章:【轉載】關於Waiting for table metadata lock的處理

在進行alter table操作時,有時會出現Waiting for table metadata lock的等待場景。而且,一旦alter table TableA的操作停滯在Waiting for table metadata lock的狀態,後續對TableA的任何操作(包括讀)都無法進行,也會在Opening tables的階段進入Waiting for table metadata lock的佇列。如果是產品環境的核心表出現了這樣的鎖等待佇列,就會造成災難性的後果。

造成alter table產生Waiting for table metadata lock的原因其實很簡單,一般是以下幾個簡單的場景:

場景一:

通過show processlist可以看到TableA上有正在進行的操作(包括讀),此時alter table語句無法獲取到metadata 獨佔鎖,會進行等待。

這是最基本的一種情形,這個和mysql 5.6中的online ddl並不衝突。一般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

場景二:

通過show processlist看不到TableA上有任何操作,但實際上存在有未提交的事務,可以在information_schema.innodb_trx中檢視到。在事務沒有完成之前,TableA上的鎖不會釋放,alter table同樣獲取不到metadata的獨佔鎖。

場景三:

通過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 但是解釋這一行為的原因很難理解,因為錯誤的語句根本不會被記錄到二進位制日誌。

總之,alter table的語句是很危險的,在操作之前最好確認對要操作的表沒有任何進行中的操作、沒有未提交事務、也沒有顯式事務中的報錯語句。如果有alter table的維護任務,在無人監管的時候執行,最好通過lock_wait_timeout設定好超時時間,避免長時間的metedata鎖等待。