Waiting for table metadata lock

本篇博客准备分两部分详细的介绍一下mysql (基于mysql 5.6)中的metadata lock,

一. 官方文档中关于Metadata Locking描述(5.6)

8.11.4 Metadata Locking

MySQL uses metadata locking to manage concurrent access to database objects and to ensure data consistency. Metadata locking applies not just to tables, but also to schemas and stored programs (procedures, functions, triggers, and scheduled events).  <span style="color:#330000;">>>mysql使用metadata locking来保证数据库对象并发访问时的数据一致性。metadata locking不仅仅用来保护表,也用来保护数据库中的其他对象,比如说 schemas,procedures,functions,triggers,scheduled events。</span>

Metadata locking does involve some overhead, which increases as query volume increases. Metadata contention increases the more that multiple queries attempt to access the same objects.  <span style="color:#330000;">>>随着访问量的增加,metadata locking所导致的开销也会增加。越多的查询访问相同的对象,产生metadata lock争用的可能越大。</span><span style="color:#ff0000;">
</span>
Metadata locking is not a replacement for the table definition cache, and its mutexes and locks differ from the LOCK_open mutex. The following discussion provides some information about how metadata locking works.  <span style="color:#330000;">>>metedata locking 不能代替 table definition cache。下面讨论了metadata locking如何工作。</span>

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 explicitly or implicitly started 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.  <span style="color:#330000;">>>为了确保事物的串行(同一个对象上),如果一个对象正在被一个未结束的事物使用(显示或者隐示),那么就不能允许其他的会话对其进行ddl操作。mysql通过在事物过程中给对象加上metadata lock来实现对象的串行访问(metadata lock在事物结束的时候被释放)。如果一个表被加上了metadata lock,那么对该表的ddl操作会被阻塞(阻塞ddl,就像“元数据锁”这个名称锁说的那样)。</span>

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: <span style="color:#ff0000;"> </span><span style="color:#330000;">>>上面说的metadata lock原则不仅针对事物表(如果innodb表),对非事物表(如myisam表)一样有效。假设一个会话开启了如下事物(事物中使用到了事物表t和非事物表nt)</span>

START TRANSACTION;
SELECT * FROM t;
SELECT * FROM nt;
The server holds metadata locks on both t and nt until the transaction ends. If another session attempts a DDL or write lock 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:  <span style="color:#330000;">>>上面的例子中mysql会对事物表t和非事物表nt都加上metadata lock直到事物结束。如果上面的事物还没有结束时,在另一个会话中进行如下操作(对t和nt进行ddl),会发现相关ddl操作都会被阻塞</span>

DROP TABLE t;
ALTER TABLE t ...;
DROP TABLE nt;
ALTER TABLE nt ...;
LOCK TABLE t ... WRITE;
If the server acquires metadata locks for a statement that is syntactically valid but fails during execution, it does not release the locks early. <span style="color:#ff0000;">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</span>.>>如果一个语法正确的语句,在执行过程中失败,加在该表上的metadata lock并不会立即释放,而是等到事物结束的时候才会释放(后面我会举例)。上面表红部分不能理解是什么意思,执行失败的语句怎么会记录到binlog中?

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.  >>在autocommit模式下,每一个语句实际上就是一个完整的事物,所以metadata lock在语句开始的时候被加上,在语句结束的时候被释放

Metadata locks acquired during a PREPARE statement are released once the statement has been prepared, even if preparation occurs within a multiple-statement transaction.  >>prepare语句获得的metadata lock在sql已经被prepare后就会被释放,即使是在一个由多个sql组成的事物中。

Before MySQL 5.5, 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.  >>在mysql 5.5之前,会在sql执行的过程中对表加一个类似metadata lock的锁,当语句结束的时候失败该锁(现在是在整个事物过程中加metadata lock,但是在autocommit模式下,也是在语句执行过程中加锁,执行结束后释放,因为一个语句即一个事物)。这种方法有一个缺点,可能会导致binlog记录顺序跟实际执行顺序不一致。

二. mysql 中出现Waiting for table metadata lock的场景

在show processlist时我们可能见到过某个语句处于Waiting for table metadata lock状态,现在我们来分析一下,在哪些情况下会出现Waiting for table metadata lock

场景1:

当一个表在被一个未结束的事物使用(包括select),另一个会话中对该表进行ddl操作时,因为无法获得独占的metadata lock该ddl操作会被阻塞,此时show processlist查看ddl操作处于Waiting for table metadata lock状态。这时我们希望知道是什么阻塞了我的ddl语句,通过下面三步,你就能找到是什么操作阻塞了你的ddl操作:

1)show processlist

如果对ddl语句造成阻塞的语句正在执行中,你通过show processlist能够发现这样的语句(查看对ddl语句中所涉及表的操作)。

2)information_schema.innodb_trx

查看innodb事物表information_schema.innodb_trx,如果在一个显示事物中(使用start transaction或者begin开启的事物),对于相关表的操作已经完成(所以show processlist无法查看到该操作),但是该事物没有被提交,此时在另一个会话中对该表进行ddl操作时,因为无法获得独占的metadata lock,该ddl操作会被阻塞。此时通过查看information_schema.innodb_trx表可以看到有活跃的事物

3)performance_schema.events_statements_current

如果某个表的ddl操作因为无法获得独占的metadata lock而被阻塞,并且查看1)和2)中的方法都没有查到相关信息,那么还有一种可能是因为在一个显式的事务中,对表a进行了一个失败的操作(比如查询了一个不存在的字段),这时事务没有开始,但是失败语句获取到的锁依然有效。从performance_schema.events_statements_current表中可以查到失败的语句。events_statements_current表记录了数据库当前thread最近一次执行的sql。

场景2:

我们知道metadata lock是用来保护数据结构的,如果表a正在被一个活跃的事物使用,另一个会话对表a的ddl操作会被阻塞。当表a的ddl操作因为无法获得独占的metadata lock(Waiting for table metadata lock)被阻塞时,后续对于表a的任何操作都会被阻塞,包括select操作(状态为Waiting for table metadata lock)

场景3:

inplace(当然5.6开始多数的ddl操作都支持online_ddl)方式对表a执行的ddl ,在ddl语句执行过程中会阻塞对于表a的所有dml操作。在online_ddl过程中不是在整个语句执行过程对表a加独占的metadata lock,在After table(online_ddl具体过程见下图),会获取metadata lock的独占锁,当进行到altering table(也是最耗时的一步)时,所有dml都是可以正常进行的。

下面是online_ddl的处理过程(profile)

+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000119 |
| checking permissions           | 0.000013 |
| checking permissions           | 0.000011 |
| init                           | 0.000007 |
| Opening tables                 | 0.007743 |
| setup                          | 0.000055 |
| creating table                 | 0.004871 |
| After create                   | 0.000152 |
| System lock                    | 0.000018 |
| preparing for alter table      | 0.009417 |
| altering table                 | 0.064343 |
| committing alter table to stor | 0.024200 |
| end                            | 0.000025 |
| query end                      | 0.002839 |
| closing tables                 | 0.000017 |
| freeing items                  | 0.000040 |
| cleaning up                    | 0.000025 |
+--------------------------------+----------+
时间: 2024-08-01 11:13:15

Waiting for table metadata lock的相关文章

MySQL出现Waiting for table metadata lock的原因以及解决方法

转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for

mysql错误: waiting for table metadata lock

今天突然发现truncate一个表都慢到不行,于是 SHOW PROCESSLIST 发现错误:waiting for table metadata lock解决方法:查看information_schema.INNODB_TRX拥有事务的trx_mysql_thread_id,kill trx_mysql_thread_id回滚事务

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

最近经常遇到mysql数据库死锁,郁闷死,show processlist; 时 Waiting for table metadata lock 能一直锁很久 下面有官网的一段话,可以理解下http://dev.mysql.com/doc/refman/5.5/en/metadata-locking.html 8.10.4. Metadata LockingMySQL 5.5.3 and up uses metadata locking to manage access to objects (

20180117MySQL出现Waiting for table metadata lock的原因以及解决方法

转自http://www.cnblogs.com/digdeep/p/4892953.html 转自:http://ctripmysqldba.iteye.com/blog/1938150 (有修改) MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包

【MySQL经典案例分析】 Waiting for table metadata lock

本文由云+社区发表 一. 问题是这样来的 ? 2018年某个周末,接到连续数据库的告警,告警信息如下: 二. 苦逼的探索过程 1.总体的思路 看到too many connection的报错信息,基本上可以把问题定位在: (1)机器负载飙升,导致SQL执行效率下降,导致连接推积 (2)业务访问量突增(或者有SQL注入现象),导致连接数打满 (3)出现"死锁"或者锁竞争严重,导致大量SQL堆积 2.排查过程 (1)机器的各项性能指标都显示正常, 没有出现高负载现象,暂时先排除了这种原因

MySQL Waiting for table metadata lock的解决方法

最近需要在某一个表中新增字段,使用Sequel Pro 或者Navicat工具都会出现程序没有反应,使用 show processlist 查看,满屏都是 Waiting for table metadata lock 状态的连接,第一反应当然是 kill 掉这些链接,但是假如太多怎么办?遂在找寻其他办法. 在网上查询得知MySQL在进行一些alter table等DDL操作时,如果该表上有未提交的事务则会出现 Waiting for table metadata lock ,而一旦出现meta

MySQL出现Waiting for table metadata lock的原因以及解决方法(转)

MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,因为他们也会在Opening tables的阶段进入到Waiting for table metadata lock的锁等待队列.如果是产品环境的核心表出现了这样的锁等待队列,就会造成

MySQL之当数据库数据源被锁(Table Metadata Lock)时的解决方案

0.发生的原因分析:[hibernate的线程池连接导致了不能修改被锁定数据库的数据库型模式] 1.关掉hibernate的所有线程池(选择退出IDE或者其他办法) 2.查看被锁的进程ID:show full processlist 3.杀掉该进程ID:kill + ID 4.提交导致数据源被锁的事务:COMMIT 或者 ROLLBACK

MySQL线程处于Waiting for table flush的分析

  最近遇到一个案例,很多查询被阻塞没有返回结果,使用show processlist查看,发现不少MySQL线程处于Waiting for table flush状态,查询语句一直被阻塞,只能通过Kill进程来解决.那么我们先来看看Waiting for table flush的官方解释:https://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html Waiting for table flush   The thread