Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【MySQL经典案例分析】 Waiting for table metadata lock

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

原创
作者头像
迪B哥
发布于 2018-12-06 07:57:15
发布于 2018-12-06 07:57:15
4.4K0
举报
文章被收录于专栏:MySQL实战分享MySQL实战分享

一、 问题是这样来的

     2018年某个周末,接到连续数据库的告警,告警信息如下:

二、 苦逼的探索过程

1、总体的思路

  看到too many connection的报错信息,基本上可以把问题定位在:

(1)机器负载飙升,导致SQL执行效率下降,导致连接推积

(2)业务访问量突增(或者有SQL注入现象),导致连接数打满

(3)出现“死锁”或者锁竞争严重,导致大量SQL堆积

2、排查过程

(1)机器的各项性能指标都显示正常, 没有出现高负载现象,暂时先排除了这种原因

(2)查看监控信息,发现在连接数打满的时间点前并没有访问量突增的趋势,同时通过检查告警信息并没有发现有注入工单

(3)最后上到服务器上查看下SQL的执行情况

①查看show full processlist;

      大量的请求都是在“Waiting for table metadata lock”,可以分成三类请求:

  • Select请求
  • Rename请求
  • Sleep请求

②分析Waiting for table metadata lock

       一般来说常见的“Waiting for table metadata lock”会出现在DDL操作或者是有未提交的事务上,从information_schema.processlist表中,没有发现有DDL操作,而能够产生MDL锁的操作也只剩下rename,但是根据SQL执行的状态,rename操作也是在等待MDL锁,所以rename操作应该是被阻塞的操作,而不是产生MDL锁的操作。

     接着我们来查看下死锁和事务的相关指标:

  •   show engine innodb status;中没有任何死锁的信息
  •   information_schema.innodb_trx 、information_schema.innodb_locks 、 information_schema.innodb_lock_waits 的也没有任何形式的锁信息。

      现在基本又排除了显示的死锁问题,那是从show full processlist中也抓不出任何请求,这里就比较疑惑了,当看了下表的结构式,发现这个表是myisam引擎的,所以上面的两种统计信息里面没有任何值就可以解释了。

      那么其实问题就集中在有未结束的事务上了,这里其实有一个误区,当时跟开发沟通存在未关闭的事务时,开发一直认为不可能,因为myisam表是不支持事务的,只有innodb支持事务。但是对于MDL锁来说,5.5之后引入MDL事务级别的锁不论对myisam还是innodb都是生效的。

③查看未提交的事务

      之后查看了下系统的事务自动提交的变量,autocommit的值是ON,那说明如果是事务未提交的话只可能是业务主动的开启一个事务,而没有commit。

      为了验证这个猜想,打开了general log,在log中果然发现,业务在开启事务后,把autocommit的值设为0了,导致必须要显示的commit才能提交事务。

这时候我们反过头来看一下host为10.49.84.70的连接请求,由于select的执行速度很快,而且访问并不频繁,所以在抽样的show processlist中,状态值大部分时间是“Sleep”,给问题的定位带来了一些迷惑性的干扰。接着我们kill掉了这个进程,果然推积的请求瞬间就执行完成了,也之间印证了刚刚上述推论。

2、问题解决

       在与开发同学沟通过程中,开发同学说库中是myisam表所以不会主动开启事务,在代码里也没有设置autocommit=0的代码,那么根本原因在哪?

       当我们定位到这台服务器上的请求都是来自python的定时脚本,使用python 操作mysql的时候,使用了其pymysql模块,但是在进行插入操作的时候,必须使用受到提交事务。Python的pymysql模块默认是会设置autocommit=0的。

      让我们来对比一下其他同样使用python访问的正常连接请求,再断开前都会手动的commit。

找到原因后有思考了下,是不是可以在建连后就设置autocommit=1呢?这样对于之后新变更的SQL就不要再考虑到手动commit的事情了,可以通过在初始化连接池的时候,对每一个连接进行设置,即

三、 延伸的一些思考

  1、metadata lock

(1)MDL简述

      为了在并发环境下维护表元数据的数据一致性,在表上有活动事务(显式或隐式)的时候,不可以对元数据进行写入操作。因此从MySQL5.5版本开始引入了MDL锁(metadata lock),来保护表的元数据信息,用于解决或者保证DDL操作与DML操作之间的一致性。

  对于引入MDL,其主要解决了2个问题,一个是事务隔离问题,比如在可重复隔离级别下,会话A在2次查询期间,会话B对表结构做了修改,两次查询结果就会不一致,无法满足可重复读的要求;另外一个是数据复制的问题,比如会话A执行了多条更新语句期间,另外一个会话B做了表结构变更并且先提交,就会导致slave在重做时,先重做alter,再重做update时就会出现复制错误的现象。所以在对表进行上述操作时,如果表上有活动事务(未提交或回滚),请求写入的会话会等待在Metadata lock wait 。

     支持事务的InnoDB引擎表和不支持事务的MyISAM引擎表,都会出现Metadata Lock Wait等待现象。一旦出现Metadata Lock Wait等待现象,后续所有对该表的访问都会阻塞在该等待上,导致连接堆积,业务受影响。

(2)常见MDL锁场景

①当前有执行DML操作时执行DDL操作

② 当前有对表的长时间查询或使用mysqldump/mysqlpump时,使用alter会被堵住

③ 显示或者隐式开启事务后未提交或回滚,比如查询完成后未提交或者回滚,DDL会被堵住

④ 表上有失败的查询事务,比如查询不存在的列,语句失败返回,但是事务没有提交,此时DDL仍然会被堵住

2、myisam、innodb对事务的支持

       Myisam是不支持事务的,innodb是支持事务的,这个概念其实没有任何问题,但是这里只的都是对于数据的事务性操作的支持,通过如下简单的实验可以很清楚的理解(关于事务的相关概念和解释就不再赘述了,只是想区别一下mysiam不支持事务,但是主动开始事务中对Myisam的操作仍然会产生MDL锁):

      在隔离级别为RC的情况下:

(1)myisam表

① CREATE TABLE `tb2` (`a` int(11) DEFAULT NULL ) ENGINE=MyISAM;

② Session 1:

       mysql> begin ;

      mysql> insert into tb2(a) value(1);

    (在session2的update之后)

      mysql> select * from tb2;

         +--------+

         |    a     |

        +--------+

         |    3     |

        +--------+

  Session 2:

      mysql> select * from tb2;

        +---------+

        |    a      |

        +---------+

       |    1       |

       +---------+

    mysql> update tb2 set a=3 where a=1;

    mysql> select * from tb2;

       +--------+

        |     a    |

        +--------+

        |    3      |

        +--------+

     mysql> alter table tb2 add b int(11);

... hangs ...

(2)innodb表

①CREATE TABLE `tb3` (`a` int(11) DEFAULT NULL ) ENGINE=INNODB;

② Session 1:

      mysql> begin ;

      mysql> insert into tb3(a) value(1);

    Session 2:

       mysql> select * from tb3;

      Empty set (0.00 sec)

3、myisam表的另一个BUG

(1)场景

① CREATE TABLE `tb2` (`a` int(11) DEFAULT NULL ) ENGINE=MyISAM;

② Session 1:

        mysql> begin ;

        mysql> select * from tb2;

    Session 2:

       mysql> create table if not exists tb2(a int);

   ... hangs ...

 ③查看show processlist

    Session 1:Sleep

    Session 2:Waiting for table metadata lock

(2)解决方式

 ①session 1上commit或者rollback

 ②另外再开一个session3 ,kill掉可疑连接

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
迪B课堂 | 匪夷所思的“too many connections”案例解析
【迪B课堂】为腾讯云数据库高级产品经理迪B哥开设的面向数据库开发者、数据库运维人员、云端运维人员的系列培训课程,旨在帮助大家从入门到精通学习和使用数据库。《我说》为迪B课堂的答疑系列,3分钟帮您解决数据库日常运维过程中的小难题。 本期为迪B课堂特刊【MySQL经典案例解析系列】第一期。搜索关注“腾讯云数据库”官方微信,回复“迪B课堂”,即可查看历史十期迪B课堂教程~ 一、故障情况 迪B哥在某个惬意的周末接到连续数据库的告警,告警信息如下: 二、艰难的探索过程 1、总体思路 看到to
腾讯云数据库 TencentDB
2019/11/20
1.8K0
迪B课堂 | 匪夷所思的“too many connections”案例解析
架构师技能5:深入MySQL原理-Waiting for table metadata lock引发系统崩溃
我们码农平时大多数时间都在撸码或者撸码的路上,很少关注mysql的一些底层原理,当出现问题时没能力第一时间解决问题,出现问题后不去层层剖析问题产生的原因,后续也就可能无法避免或者绕开同类的问题。因此不要单纯做Ctrl+c和Ctrl+V,而是一边仰望星空(目标规划),一边脚踏实地去分析每个问题。 在mysql系列专栏里面,我深入浅出的总结了mysql相关知识,感兴趣的话可以去阅读,有问题就可以随时相互交流学习。
黄规速
2022/04/14
1.2K0
架构师技能5:深入MySQL原理-Waiting for table metadata lock引发系统崩溃
MySQL5.7+查看Waiting for table metadata lock 锁情况
Waiting for table metadata lock 这个mdl锁,我们最常见,这篇先拿它开刀。
保持热爱奔赴山海
2020/07/27
3.8K0
MySQL5.7+查看Waiting for table metadata lock  锁情况
MetaData Lock 之三
一 简介 通过前面两篇文章的介绍,相信读到这里的各位对MDL 锁已经有了比较深入的了解了,本文将结合理论知识介绍几组MDL 锁的案例。 二 常见MDL 锁的场景 1 Waiting for global read lock 我们先构造一个Waiting for global read lock场景: session1: alter table t1 add c3 bigint; //大表执行需较长时间 session2: set global read only=on; //等待 查看
用户1278550
2018/08/09
7570
【MySQL】metadata lock问题
MySQL使用DML来管理对数据库对象的并发访问,并确保数据一致性。DML不仅适用于表,还适用于模式和存储程序(过程、函数、触发器和计划的事件)
用户5522200
2020/06/11
1.7K0
alter table锁表,MySQL出现Waiting for table metadata lock的场景浅析及解决方案
在修改/增加表字段的时候,发现很慢, 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,
小小科
2018/05/03
3.4K0
alter table锁表,MySQL出现Waiting for table metadata lock的场景浅析及解决方案
waiting for metadata lock对腾讯云从节点的影响及处理
某用户A反馈CDB实例读业务数据库没有响应,在控制台界面看到ro节点被剔除,剔除之前数据库监控上面cpu负载正常,活跃线程数出现大量的堆积;提单后,平台紧急介入,观察到ro节点出现大量的waiting for table metadata lock的报错。
vkyzhao
2020/12/21
1.4K0
waiting for metadata lock对腾讯云从节点的影响及处理
MySQL表结构变更,不可不知的Metadata Lock
在线上进行DDL操作时,相对于其可能带来的系统负载,其实,我们最担心的还是MDL其可能导致的阻塞问题。
星哥玩云
2022/08/17
4800
MySQL表结构变更,不可不知的Metadata Lock
MetaData Lock 之二
一 简介 上一篇文章 《MetaData Lock 之一》 简单的介绍了MySQL 引入MDL 的前因后果,本文深入了解MDL的实现原理和运行机制。
用户1278550
2018/08/09
7750
MySQL出现Waiting for table metadata lock的场景浅析
在进行alter table操作时,有时会出现Waiting for table metadata lock的等待场景。而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)都无法进行,也会在Opening tables的阶段进入Waiting for table metadata lock的队列。如果是产品环境的核心表出现了这样的锁等待队列,就会造成灾难性的后果。
星哥玩云
2022/08/17
8310
MySQL出现Waiting for table metadata lock的场景浅析
Waiting for table metadata lock问题处理
在使用mysql的时候,我们有时会碰到Waiting for table metadata lock的锁等待。但是这个锁等待比较特殊,在innodb_lock_wait和show engine innodb status 表里面都查不到。
老叶茶馆
2020/06/24
1.8K0
MySQL Online DDL导致全局锁表案例分析
线上给某个表执行新增索引SQL, 然后整个数据CPU打到100%, 连接数暴增到极限, 最后导致所有访问数据库的应用都奔溃.
李国宝
2019/05/11
1.8K0
深入理解MDL元数据锁
当你在MySQL中执行一条SQL时,语句并没有在你预期的时间内执行完成,这时候我们通常会登陆到MySQL数据库上查看是不是出了什么问题,通常会使用的一个命令就是 show processlist,看看有哪些session,这些session在做什么事情。当你看到 waiting for table metadata lock 时,那就是遇到MDL元数据锁了。本篇文章将会介绍MDL锁的产生与排查过程。
MySQL技术
2019/12/12
3.2K0
技术分享 | MySQL 的 MDL 锁解惑
网名 bisal ,具有十年以上的应用运维工作经验,目前主要从事数据库应用研发能力提升和技术管理相关的工作,Oracle ACE ,腾讯云TVP,拥有 Oracle OCM & OCP 、EXIN DevOps Master 、SCJP 等国际认证,国内首批 Oracle YEP 成员,OCMU 成员,《DevOps 最佳实践》中文译者之一,CSDN & ITPub 专家博主,公众号"bisal的个人杂货铺",长期坚持分享技术文章,多次在线上和线下分享技术主题。
爱可生开源社区
2022/05/23
1.4K0
技术分享 | MySQL 的 MDL 锁解惑
聊聊 MySQL 的 Online DDL
日常开发我们对一条DML语句较为熟悉,很多开发人员都了解sql的执行过程,比较熟悉,但是DDL是如何执行的呢,大部分开发人员可能不太关心,也认为没必要了解,都交给DBA吧。其实不然,了解一些能尽量避开一些ddl的坑,那么下面带大家一起了解一下DDL执行的方式,也算抛砖引玉吧。如有错误,还请各位大佬们指正。
码猿技术专栏
2023/09/07
1.3K0
聊聊 MySQL 的 Online DDL
pt-online-schema-change使用
如果说你的数据量并发量不大,或者你的数据量很少没有到千万级别,也许pt-osc、gh-osc,online-ddl这些工具都用不着。但是,如果你的数据量很大,数据又很热。如果你没有这些工具,你可能无法完成对一个数据库新增一个字段或者任何一个简单的DDL语句。
chengcheng222e
2021/11/03
1K0
pt-online-schema-change使用
waiting for table metadata lock的一种解决方法
对MySQL进行alter table等DDL操作时,有时会发现对某个表的任何操作都被阻塞,包括读,报错如下图所示
于航
2019/08/10
10.2K0
有爱有恨的MDL锁
MySQL 5.5 中就引入了metadata lock(元数据锁)。用于对管理 database objects(数据库对象)的并发访问,保证数据的一致性。
田帅萌
2018/08/14
6890
有爱有恨的MDL锁
【MySQL入门】之MySQL数据库的锁机制(一)
数据库锁机制简单来说,就是数据库在多事务并发处理时,为了保证数据的一致性和完整性,数据库需要合理地控制资源的访问规则。锁是一种资源,这个资源是和事务关联在一起的,当某个事务获取了锁,在提交或回滚之前,就一直持有该锁。
MySQL数据库技术栈
2020/08/05
1.6K0
遇到MDL锁,如何分析和处理?
之前遇到一个DBA,在生产库上加字段,导致数据库连接数打满。原因就是MDL锁引起。下面让我来介绍一下MDL锁及其排查和处理方式。
用户10842762
2023/11/15
7671
相关推荐
迪B课堂 | 匪夷所思的“too many connections”案例解析
更多 >
交个朋友
加入[数据] 腾讯云技术交流站
获取数据实战干货 共享技术经验心得
加入数据技术工作实战群
获取实战干货 交流技术经验
加入[数据库] 腾讯云官方技术交流站
数据库问题秒解答 分享实践经验
换一批
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档