场景
调研环境下,对一张千万条数据的表做了一个truncate操作,发现长时间无反应。
解决思路
操作一直执行,决定查询下正在执行的sql的状态
shop processlist;
发现truncate操作的状态是:Waiting for table metadata lock。
查询正在执行的事务:
select * from information_schema.innodb_trx\G
找到了操作表的那个事务,有insert语句没有提交,查看事务的trx_mysql_thread_id,然后执行kill [id]删除。
卡住的sql就都执行成功了。
思考
MDL是为了保护database objects而设计的。
MDL和事务的关系是,在事务中,当访问一个database object时都先要获得其MDL,在事务结束后才会释放MDL。
这样做有几个目的:
第一是为了进一步保证事务的一致性,比如事务A对某一行记录进行了更新,还没有提交,但这时另外一个会话2要修改表名,如果事务 A 持有MDL,那另一个会话2将无法修改,show processlist会发现它在Waiting for table metadata lock。直到事务 A 提交或回滚后,才能获得MDL修改成功。
第二是为了解决 binlog 同步的一个 bug,这个和上面的原因一样。binlog 的操作是基于事务的提交顺序的。事务 A 还未提交,另一个会话删除了相关表,这样 binlog 先记录的是删除表的操作,从库执行的顺序就不对了。
来源:oschina
链接:https://my.oschina.net/u/2450666/blog/3138238