MDL锁导致mysql夯住_MySQL MetaData Lock 案例分享
前言:今天開發童鞋遇到一個奇怪的問題,在測試環境里面執行drop database dbname發現一直夯住不動,等了很久也沒有執行,于是問題就到我這里了
一、什么是MetaData Lock?
MetaData Lock即元數據鎖,在數據庫中元數據即數據字典信息包括db,table,function,procedure,trigger,event等。metadata lock主要為了保證元數據的一致性,用于處理不同線程操作同一數據對象的同步與互斥問題
二、MetaData Lock的前世今生
mdl鎖是為了解決一個有名的bug#989,所以在5.5.3版本引入了MDL鎖。其實5.5也有類似保護元數據的機制,只是沒有明確提出MDL概念而已。但是5.5之前版本(比如5.1)與5.5之后版本在保護元數據這塊有一個顯著的不同點是,5.1對于元數據的保護是語句級別的,5.5對于metadata的保護是事務級別的。所謂語句級別,即語句執行完成后,無論事務是否提交或回滾,其表結構可以被其他會話更新;而事務級別則是在事務結束后才釋放MDL。引入MDL鎖主要是為了解決兩個問題:
事務隔離問題:比如在可重復隔離級別下,會話A在2次查詢期間,會話B對表結構做了修改,兩次查詢結果就會不一致,無法滿足可重復讀的要求。
數據復制問題:比如會話A執行了多條更新語句期間,另外一個會話B做了表結構變更并且先提交,就會導致slave在重做時,先重做alter,再重做update時就會出現復制錯誤的現象。也就是上面提到的bug#989。
三、Waiting For Table?MetaData Lock場景重現(這也是我們今天遇到的問題)
session A:注意這里是顯示的提交一個事務
root@localhost:mysql.sock 18:03:49 [tom]>desc test;
+------------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+-------------------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| name | varchar(32) | YES | | NULL | |
| age | int(10) | YES | | NULL | |
| createtime | datetime | NO | | CURRENT_TIMESTAMP | |
+------------+-------------+------+-----+-------------------+----------------+
4 rows in set (0.01 sec)
root@localhost:mysql.sock 18:03:43 [tom]>start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql.sock 18:03:46 [tom]>select c99 from test;
ERROR 1054 (42S22): Unknown column 'c99' in 'field list'
session B:執行Online DDL(我這個是MySQL5.7.14官方版本哦)
root@localhost:mysql.sock 18:02:26 [tom]>Start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql.sock 18:04:16 [tom]>alter table test drop column age;
發生阻塞...
session C:processlist看不到任何test表操作,但是有MDL鎖
root@localhost:mysql.sock 18:02:31 [tom]>show processlist;
+-------+---------+----------------+------+---------+------+---------------------------------+----------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+---------+----------------+------+---------+------+---------------------------------+----------------------------------+
| 743 | monitor | 10.0.0.6:54020 | NULL | Sleep | 3 | | NULL |
| 92210 | monitor | 10.0.0.6:46778 | NULL | Sleep | 1 | | NULL |
| 93740 | root | localhost | tom | Query | 0 | starting | show processlist |
| 93742 | root | localhost | tom | Sleep | 64 | | NULL |
| 93743 | root | localhost | tom | Query | 8 | Waiting for table metadata lock | alter table test drop column age |
+-------+---------+----------------+------+---------+------+---------------------------------+----------------------------------+
5 rows in set (0.00 sec)
innodb engine監控看不到任何鎖沖突信息
------------
TRANSACTIONS
------------
Trx id counter 112477
Purge done for trx's n:o < 112477 undo n:o < 0 state: running but idle
History list length 556
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421340178270032, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421340178271856, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421340178270944, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
查看information_schema
root@localhost:mysql.sock 18:18:46 [tom]>select trx_id,trx_state,trx_started,trx_mysql_thread_id from information_schema.innodb_trx;
Empty set (0.00 sec)
這種情況是一個特例,存在一個查詢失敗的語句,比如查詢不存在的列,語句失敗返回,但是事務沒有提交,此時alter仍然會被堵住。通過show processlist看不到表上有任何操作,在information_schema.innodb_trx中也沒有任何進行中的事務。這很可能是因為在一個顯式的事務中,對表進行了一個失敗的操作(比如查詢了一個不存在的字段),這時事務沒有開始,但是失敗語句獲取到的鎖依然有效。從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.
定位問題SQL,然后殺掉對應的SQL。查看每一個session正在執行的sql,然后通過下面語句定位到問題sql,殺掉就可以了
select * from performance_schema.events_statements_current\G
select * from sys.session\G
select * from sys.processlist\G
為了方便大家交流,本人開通了微信公眾號,和QQ群291519319。喜歡技術的一起來交流吧
總結
以上是生活随笔為你收集整理的MDL锁导致mysql夯住_MySQL MetaData Lock 案例分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 买电脑主要看什么配置_买笔记本电脑主要看
- 下一篇: 无锡c语言编程培训学校,无锡c语言培训班