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的锁等待队列。如果是产品环境的核心表出现了这样的锁等待队列,就会造成灾难性的后果。

造成alter table产生Waiting for table metadata lock的原因其实很简单,一般是以下几个简单的场景:

场景一:长事物运行,阻塞DDL,继而阻塞所有同表的后续操作

通过show processlist可以看到TableA上有正在进行的操作(包括读),此时alter table语句无法获取到metadata 独占锁,会进行等待。

这是最基本的一种情形,这个和mysql 5.6中的online ddl并不冲突。一般alter table的操作过程中(见下图),在after create步骤会获取metadata 独占锁,当进行到altering table的过程时(通常是最花时间的步骤),对该表的读写都可以正常进行,这就是online ddl的表现,并不会像之前在整个alter table过程中阻塞写入。(当然,也并不是所有类型的alter操作都能online的,具体可以参见官方手册:http://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html)
处理方法: kill 掉 DDL所在的session.

场景二:未提交事物,阻塞DDL,继而阻塞所有同表的后续操作

通过show processlist看不到TableA上有任何操作,但实际上存在有未提交的事务,可以在 information_schema.innodb_trx中查看到。在事务没有完成之前,TableA上的锁不会释放,alter table同样获取不到metadata的独占锁。

处理方法:通过 select * from information_schema.innodb_trx\G, 找到未提交事物的sid, 然后 kill 掉,让其回滚。

场景三:

通过show processlist看不到TableA上有任何操作,在information_schema.innodb_trx中也没有任何进行中的事务。这很可能是因为在一个显式的事务中,对TableA进行了一个失败的操作(比如查询了一个不存在的字段),这时事务没有开始,但是失败语句获取到的锁依然有效,没有释放。从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.

也就是说除了语法错误,其他错误语句获取到的锁在这个事务提交或回滚之前,仍然不会释放掉。because the failed statement is written to the binary log and the locks protect log consistency 但是解释这一行为的原因很难理解,因为错误的语句根本不会被记录到二进制日志。

处理方法:通过performance_schema.events_statements_current找到其sid, kill 掉该session. 也可以 kill 掉DDL所在的session.

总之,alter table的语句是很危险的(其实他的危险其实是未提交事物或者长事务导致的),在操作之前最好确认对要操作的表没有任何进行中的操作、没有未提交事务、也没有显式事务中的报错语句。如果有alter table的维护任务,在无人监管的时候运行,最好通过lock_wait_timeout设置好超时时间,避免长时间的metedata锁等待。

(0)

相关推荐

  • 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中的alter table命令的基本使用方法及提速优化

    一.基本用法 1. 增加列 alter table tbl_name add col_name type 例如,  给pet的表增加一列 weight, mysql>alter table pet add weight int; 2. 删除列 alter table tbl_name drop col_name 例如, 删除pet表中的weight这一列 mysql>alter table pet drop weight; 3. 改变列 分为改变列的属性和改变列的名字 改变列的属性--方法1:

  • MYSQL METADATA LOCK(MDL LOCK)MDL锁问题分析

    一.前言 MYSQL中MDL锁一直是一个比较让人比较头疼的问题,我们谈起锁一般更加倾向于INNODB下层的gap lock.next key lock.row lock等,因为它很好理解,也很好观察,而对于MDL LOCK却了解得很少,因为它实在不好观察,只有出现问题查看show processlist勉强可以看到 简单的所谓的Waiting for table metadata lock之类的状态,其实MDL LOCK是MYSQL上层一个非常复杂的子系统,有自己的死锁检测机制 (无向图?)而大

  • MySQL表结构变更你不可不知的Metadata Lock详解

    前言 想必玩过mysql的人对Waiting for table metadata lock肯定不会陌生,一般都是进行alter操作时被堵住了,导致了我们在show processlist 时,看到线程的状态是在等metadata lock.本文会对MySQL表结构变更的Metadata Lock进行详细的介绍. 在线上进行DDL操作时,相对于其可能带来的系统负载,其实,我们最担心的还是MDL其可能导致的阻塞问题. 一旦DDL操作因获取不到MDL被阻塞,后续其它针对该表的其它操作都会被阻塞.典型

  • MYSQL METADATA LOCK(MDL LOCK) 理论及加锁类型测试

    目录 MYSQL METADATA LOCK(MDL LOCK)学习 理论知识和加锁类型测试 一.初步了解 二.基础重要的数据结构(类)和概念 1.MDL TYPE 2.MDL NAMESPACE 3.实现分类 4.MDL兼容矩阵 5.MDL duration及MDL持续到什么时候 6.MDL LOCK FAST PATH(unobtrusive) OR SLOW PATH(obtrusive) 7.MDL_request类 7.MDL_key类 8.MDL_ticket 9.MDL_lock

  • MySQL部署时提示Table mysql.plugin doesn’t exist的解决方法

    今天部署了免安装版的MySQL,出现了Table 'mysql.plugin' doesn't exist的问题,苦恼了好久,终于在网上找到了解决方案,现整理一下给大家分享: 系统环境:Win10 64位 MySQL版本:mysql-5.7.17-winX64 部署的步骤就是按照网上说的: 1:修改环境变量path,增加值C:\Program Files\mysql-5.7.17-winX64\bin 2:修改my-default.ini,重命名为my.ini,修改文件内容: # basedir

  • 将MySQL help contents的内容有层次的输出方法推荐

    经常会遇到这种情况,在一个不能上网的环境通过MySQL客户端登录数据库,想执行一个操作,却忘了操作的具体语法,各种不方便. 其实,MySQL数据库内置了帮助文档,通过help contents即可查看. 如下所示: 可见,该文档涵盖了数据库操作的大部分主题. 文档分为以上几大类,每个大类又包括更小粒度的类,类最后有具体的topic组成. 那么这之间的层级关系如何呢? 昨天想执行一个操作 mysql> backup table emp to '/tmp/mysqlbackup'; 因为这个back

  • mysql 大表批量删除大量数据的实现方法

    问题参考自:https://www.zhihu.com/question/440066129/answer/1685329456 ,mysql中,一张表里有3亿数据,未分表,其中一个字段是企业类型,企业类型是一般企业和个体户,个体户的数据量差不多占50%,根据条件把个体户的行都删掉.请问如何操作?答案为个人原创 假设表的引擎是 Innodb, MySQL 5.7+ 删除一条记录,首先锁住这条记录,数据原有的被废弃,记录头发生变化,主要是打上了删除标记.也就是原有的数据 deleted_flag

  • MySql中表单输入数据出现中文乱码的解决方法

     MySQL会出现中文乱码的原因在于 1.server本身设定问题,一般来说是latin1 2.建库建表时没有制定编码格式. MySql中表单输入数据出现中文乱码的解决方法: 1.建库的时候 CREATE DATABASE test CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; 2.建表的时候 CREATE TABLE content ( text VARCHAR(100) ) ENGINE=InnoDB DEFAULT CHARSET=utf8

  • 设置MySQL自动增长从某个指定的数开始方法

    自增字段,一定要设置为primary key. 以指定从1000开始为例. 1 创建表的时候就设置: CREATE TABLE `Test` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `NAME` varchar(50) NOT NULL, `SEX` varchar(2) NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=MEMORY AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 CHECKSU

随机推荐