MDL锁导致mysql夯住_MySQL MetaData Lock 案例分享
前言:今天開發(fā)童鞋遇到一個(gè)奇怪的問(wèn)題,在測(cè)試環(huán)境里面執(zhí)行drop database dbname發(fā)現(xiàn)一直夯住不動(dòng),等了很久也沒(méi)有執(zhí)行,于是問(wèn)題就到我這里了
一、什么是MetaData Lock?
MetaData Lock即元數(shù)據(jù)鎖,在數(shù)據(jù)庫(kù)中元數(shù)據(jù)即數(shù)據(jù)字典信息包括db,table,function,procedure,trigger,event等。metadata lock主要為了保證元數(shù)據(jù)的一致性,用于處理不同線程操作同一數(shù)據(jù)對(duì)象的同步與互斥問(wèn)題
二、MetaData Lock的前世今生
mdl鎖是為了解決一個(gè)有名的bug#989,所以在5.5.3版本引入了MDL鎖。其實(shí)5.5也有類似保護(hù)元數(shù)據(jù)的機(jī)制,只是沒(méi)有明確提出MDL概念而已。但是5.5之前版本(比如5.1)與5.5之后版本在保護(hù)元數(shù)據(jù)這塊有一個(gè)顯著的不同點(diǎn)是,5.1對(duì)于元數(shù)據(jù)的保護(hù)是語(yǔ)句級(jí)別的,5.5對(duì)于metadata的保護(hù)是事務(wù)級(jí)別的。所謂語(yǔ)句級(jí)別,即語(yǔ)句執(zhí)行完成后,無(wú)論事務(wù)是否提交或回滾,其表結(jié)構(gòu)可以被其他會(huì)話更新;而事務(wù)級(jí)別則是在事務(wù)結(jié)束后才釋放MDL。引入MDL鎖主要是為了解決兩個(gè)問(wèn)題:
事務(wù)隔離問(wèn)題:比如在可重復(fù)隔離級(jí)別下,會(huì)話A在2次查詢期間,會(huì)話B對(duì)表結(jié)構(gòu)做了修改,兩次查詢結(jié)果就會(huì)不一致,無(wú)法滿足可重復(fù)讀的要求。
數(shù)據(jù)復(fù)制問(wèn)題:比如會(huì)話A執(zhí)行了多條更新語(yǔ)句期間,另外一個(gè)會(huì)話B做了表結(jié)構(gòu)變更并且先提交,就會(huì)導(dǎo)致slave在重做時(shí),先重做alter,再重做update時(shí)就會(huì)出現(xiàn)復(fù)制錯(cuò)誤的現(xiàn)象。也就是上面提到的bug#989。
三、Waiting For Table?MetaData Lock場(chǎng)景重現(xiàn)(這也是我們今天遇到的問(wèn)題)
session A:注意這里是顯示的提交一個(gè)事務(wù)
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:執(zhí)行Online DDL(我這個(gè)是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;
發(fā)生阻塞...
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監(jiān)控看不到任何鎖沖突信息
------------
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)
這種情況是一個(gè)特例,存在一個(gè)查詢失敗的語(yǔ)句,比如查詢不存在的列,語(yǔ)句失敗返回,但是事務(wù)沒(méi)有提交,此時(shí)alter仍然會(huì)被堵住。通過(guò)show processlist看不到表上有任何操作,在information_schema.innodb_trx中也沒(méi)有任何進(jìn)行中的事務(wù)。這很可能是因?yàn)樵谝粋€(gè)顯式的事務(wù)中,對(duì)表進(jìn)行了一個(gè)失敗的操作(比如查詢了一個(gè)不存在的字段),這時(shí)事務(wù)沒(méi)有開始,但是失敗語(yǔ)句獲取到的鎖依然有效。從performance_schema.events_statements_current表中可以查到失敗的語(yǔ)句。
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.
定位問(wèn)題SQL,然后殺掉對(duì)應(yīng)的SQL。查看每一個(gè)session正在執(zhí)行的sql,然后通過(guò)下面語(yǔ)句定位到問(wèn)題sql,殺掉就可以了
select * from performance_schema.events_statements_current\G
select * from sys.session\G
select * from sys.processlist\G
為了方便大家交流,本人開通了微信公眾號(hào),和QQ群291519319。喜歡技術(shù)的一起來(lái)交流吧
總結(jié)
以上是生活随笔為你收集整理的MDL锁导致mysql夯住_MySQL MetaData Lock 案例分享的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 买电脑主要看什么配置_买笔记本电脑主要看
- 下一篇: 无锡c语言编程培训学校,无锡c语言培训班