mysql出现Waiting for table metadata lock的原因及解决方案

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


最近经常遇到mysql数据库死锁,郁闷死, 
show processlist; 时 Waiting for table metadata lock 能一直锁很久 


下面有官网的一段话,可以理解下 
http://dev.mysql.com/doc/refman/5.5/en/metadata-locking.html 


8.10.4. Metadata Locking 
MySQL 5.5.3 and up uses metadata locking to manage access to objects (tables, triggers, and so forth). Metadata locking is used to ensure data consistency but does involve some overhead, which increases as query volume increases. Metadata contention increases the more that multiple queries attempt to access the same objects. 


Metadata locking is not a replacement for the table definition case, and its mutxes and locks differ from the LOCK_open mutex. The following discussion provides some information about how metadata locking works. 


To ensure transaction serializability, the server must not permit one session to perform a data definition language (DDL) statement on a table that is used in an uncompleted transaction in another session. The server achieves this by acquiring metadata locks on tables used within a transaction and deferring release of those locks until the transaction ends. A metadata lock on a table prevents changes to the table's structure. This locking approach has the implication that a table that is being used by a transaction within one session cannot be used in DDL statements by other sessions until the transaction ends. 


This principle applies not only to transactional tables, but also to nontransactional tables. Suppose that a session begins a transaction that uses transactional table t and nontransactional table nt as follows: 


START TRANSACTION; 
SELECT * FROM t; 
SELECT * FROM nt; 
Metadata locks are held on both t and nt until the transaction ends. If another session attempts a DDL operation on either table, it blocks until metadata lock release at transaction end. For example, a second session blocks if it attempts any of these operations: 


DROP TABLE t; 
ALTER TABLE t ...; 
DROP TABLE nt; 
ALTER TABLE nt ...; 
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. 


In autocommit mode, each statement is in effect a complete transaction, so metadata locks acquired for the statement are held only to the end of the statement. 


Metadata locks acquired during a PREPARE statement are released once the statement has been prepared, even if preparation occurs within a multiple-statement transaction. 


Before MySQL 5.5.3, when a transaction acquired the equivalent of a metadata lock for a table used within a statement, it released the lock at the end of the statement. This approach had the disadvantage that if a DDL statement occurred for a table that was being used by another session in an active transaction, statements could be written to the binary log in the wrong order 


一个没提交的事务使用了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. 


MySQL 5.6 enhances many other types OF ALTER TABLE operations TO avoid copying the TABLE.  
Another enhancement allows SELECT queries AND INSERT, UPDATE, AND DELETE (DML) statements TO proceed while the TABLE IS being altered.  
This combination OF features IS now known AS online DDL. 
那么就让alter table wait去吧。 


后来又发现另外一个神奇的事: 
mysql [localhost] {msandbox} (spc) > SHOW processlist; 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
| Id | USER     | Host      | db   | Command | TIME | State                           | Info                                | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
|  5 | msandbox | localhost | spc  | Query   |    1 | Waiting FOR TABLE metadata LOCK | ALTER TABLE t ADD INDEX(play_count) | 
|  8 | msandbox | localhost | spc  | Query   |    3 | USER sleep                      | SELECT sleep(100) FROM t            | 
| 10 | msandbox | localhost | spc  | Query   |    0 | init                            | SHOW processlist                    | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 


重启后再试一次: 
mysql [localhost] {msandbox} (spc) > SHOW processlist; 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
| Id | USER     | Host      | db   | Command | TIME | State                           | Info                                | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 
|  1 | msandbox | localhost | spc  | Query   |  129 | USER sleep                      | SELECT sleep(100) FROM t            | 
|  2 | msandbox | localhost | spc  | Query   |  102 | Waiting FOR TABLE metadata LOCK | ALTER TABLE t DROP INDEX play_count | 
|  3 | msandbox | localhost | spc  | Query   |    0 | init                            | SHOW processlist                    | 
+----+----------+-----------+------+---------+------+---------------------------------+-------------------------------------+ 


这个sleep的时间。。。已经超过100秒了… 


结论: 
在准备alter table tbl 的时候,先观察一下,有没有正在运行的,且在短时间内无法结束的sql语句在操作tbl表

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 8中的“waiting for table metadata lock”错误通常表示在运行某个查询或DML语句时,另一个进程已经占据了需要访问的数据表或索引,导致当前进程无法获取到对应的元数据锁,从而无法继续执行。 元数据锁是MySQL中的一种排他锁,用于保护数据表的元数据信息(例如表结构、索引信息等)。当一个进程需要查询或修改数据表的元数据时,它会请求获得对应的元数据锁,以保证自己能够独占这些元数据信息的访问。但是,如果另一个进程已经占据了相应的锁,当前进程就需要等待锁的释放才能继续执行,这就是“waiting for table metadata lock”的错误原因。 为了避免这个问题,我们可以尝试采取以下措施: 1. 使用更高的隔离级别(如repeatable read或serializable)来保证访问数据表时的可重复读性,从而减少对元数据的频繁访问和锁冲突的机会。 2. 减少对数据表结构的频繁修改操作,避免在高并发环境中进行DDL语句(如ALTER TABLE)的执行。 3. 尽量避免将多个操作合并成一条长SQL语句,尽可能将多个小操作拆分成多条短SQL语句,从而减少对数据表的锁定时间。 4. 使用更高效的数据库架构设计(如分库分表、索引优化等),将数据的读写操作分配到更多的物理资源中,从而减少对单个数据表的锁定时间。 在实际进行MySQL数据库开发或运维时,我们需要注意以上几点,以避免“waiting for table metadata lock”错误的发生。如果不幸遇到此类问题,我们需要通过查看进程列表、慢查询日志、错误日志或排查sql执行计划等方式,以找出造成锁冲突的根本原因。针对不同的错误原因,我们可以采取不同的解决方法,从而有效避免MySQL 8中的元数据锁问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值