我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Mysql解决USE DB堵塞详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Mysql解决USE DB堵塞详解

遇到故障,我们往往想的是如何解决这个故障,而不是从故障的根本去思考出现这个故障的原因?这样的结果,只能使我们得到了鱼,失去了渔。今天,我们就来分享一个由USE DB堵塞故障引发的思考案例。

故障描述

今天一个朋友遇到数据库遇到一个严重的故障,故障环境如下:

MYSQL 5.6.16

RR隔离级别

GITD关闭

表现如下:

use db不能进入数据库

show table status不能查询到表信息

schema.processlist来看有大量的 Waiting for table metadata lock

情急之下他杀掉了一大堆线程后发现还是不能恢复,最后杀掉了一个没有及时提交的事物才恢复正常。也仅仅留下了如下图的一个截图:

Mysql解决USE DB堵塞详解

故障信息提取

还是回到上图,我们可以归纳一下语句类型如下:

1、CREATE TABLE A AS SELECT B

其STATE为 sending data

2、DROP TABLE A

其STATE为 Waiting for table metadata lock

3、SELECT * FROM A

其STATE为 Waiting for table metadata lock

4、 SHOW TABLE STATUS[like 'A']

其STATE为 Waiting for table metadata lock

信息分析

要分析出这个案列其实不太容易因为他是MYSQL层MDL LOCK和RR模式innodb row lock的一个综合案列,并且我们要对schema.processlist的STATE比较敏感才行。

建议先阅读我的如下文章来学习MDL LOCK:

https://www.jb51.net/article/131383.htm

本节关于MDL LOCK的验证使用下面两种方式:

方式一:笔者在MDL LOCK源码加锁函数处加日志输出,如果要分析各种语句加MDL LOCK的类型还只能用这种方式,因为MDL LOCK加锁往往一闪而过,performance_schema.metadata_locks 没有办法观察到。

方式二:处于堵塞情况下使用5.7版本的performance_schema.metadata_locks观察。

在P_S中打开mdl监测方法如下:

Mysql解决USE DB堵塞详解

一、关于CREATE TABLE A AS SELECT B 对B表sending data的分析

关于sending data这个状态其实可以代表很多含义,从我现有的对的了解,这是MYSQL上层对SELECT类型语句的这类语句在INNODB层和MYSQL层进行数据交互的时候一个统称,所以出现它的可能包含:

确实需要访问数据量特别大,可能需要优化。

由于INNODB 层的获取row lock需要等待,比如我们常见的SELECT FOR UPDATE。

同时我们还需要注意在RR模式下SELECT B这一部分加锁方式和INSERT...SELECT是一致的参考不再赘述:

从他反应的情况因为他在最后杀掉了一个长期的未提交的事物所以他因为是情况2。并且整个CREATE TABLE A AS SELECT B语句由于B表上某些数据库被上了锁而不能获取,导致整个语句处于sending data状态下。

二、关于SHOW TABLE STATUS[like 'A'] Waiting for table metadata lock的分析

这是本案例中最重要的一环,SHOW TABLE STATUS[like 'A']居然被堵塞其STATE为Waiting for table metadata lock并且注意这里是table因为MDL LOCK类型分为很多。我在MDL介绍的那篇文章中提到了desc 一个表的时候会上MDL_SHARED_HIGH_PRIO(SH),其实在SHOW TABLE STATUS的时候也会对本表上MDL_SHARED_HIGH_PRIO(SH)。

方式一

Mysql解决USE DB堵塞详解

方式二

Mysql解决USE DB堵塞详解

两种方式都能观察到MDL_SHARED_HIGH_PRIO(SH)的存在并且我模拟的是处于堵塞情况下的。

但是MDL_SHARED_HIGH_PRIO(SH) 是一个优先级非常高的一个MDL LOCK类型表现如下:

兼容性:

Mysql解决USE DB堵塞详解

阻塞队列优先级:

Mysql解决USE DB堵塞详解

其被堵塞的条件除了被MDL_EXCLUSIVE(X)堵塞没有其他的可能。那么这就是一个非常重要的突破口。

三、关于CREATE TABLE A AS SELECT B 对A表的加MDL LOCK的分析

这一点也是我以前不知道的,也是本案列中花时间最多的地方,前文已经分析过要让SHOW TABLE STATUS[like 'A']这种只会上MDL_SHARED_HIGH_PRIO(SH) MDL LOCK的语句堵塞在MDL LOCK上只有一种可能那就是A表上了MDL_EXCLUSIVE(X)。

那么我开始怀疑这个DDL语句在语句结束之前会对A表上MDL_EXCLUSIVE(X) ,然后进行实际测试不出所料确实是这样的如下:

方式一

Mysql解决USE DB堵塞详解

方式二

Mysql解决USE DB堵塞详解

这里比较遗憾在performance_schema.metadata_locks中并没有显示出MDL_EXCLUSIVE(X),而显示为MDL_SHARED(S)是我们在我输出的日志中可以看到这里做了升级操作将MDL_SHARED(S) 升级为了MDL_EXCLUSIVE(X)。并且由前面的兼容性列表来看,只有MDL_EXCLUSIVE(X)会堵塞MDL_SHARED_HIGH_PRIO(SH)。所以我们应该能够确认这里确实做了升级操作,否则SHOW TABLE STATUS[like 'A'] 是不会被堵塞的。

四、关于SELECT * FROM A Waiting for table metadata lock的分析

也许大家认为SELECT不会上锁,但是那是在innodb 层次,在MYSQL层会上MDL_SHARED_READ(SR) 如下:

方式一

Mysql解决USE DB堵塞详解

方式二

Mysql解决USE DB堵塞详解

可以看到确实有MDL_SHARED_READ(SR)的存在,当前处于堵塞状态

其兼容性如下:

Mysql解决USE DB堵塞详解

显然MDL_SHARED_READ(SR) 和MDL_SHARED_HIGH_PRIO(SH)是不兼容的需要等待。

五、关于DROP TABLE A Waiting for table metadata lock的分析

这一点很好分析因为A表上了X锁而DROP TABLE A必然上MDL_EXCLUSIVE(X)锁它当然和MDL_EXCLUSIVE(X)不兼容。如下:

方式一

Mysql解决USE DB堵塞详解

方式二

Mysql解决USE DB堵塞详解

其中EXCLUSIVE就是我们说的MDL_EXCLUSIVE(X)它确实存在当前处于堵塞

六、为何use db也会堵塞?

如果使用mysql客户端不使用-A选项(或者 no-auto-rehash)在USE DB的时候至少要做如下事情:

1、 对db下每个表上MDL (SH) lock如下(调用MDL_context::acquire_lock 这里给出堵塞时候的信息)

方式一

Mysql解决USE DB堵塞详解

方式二

Mysql解决USE DB堵塞详解

可以看到USE DB确实也因为MDL_SHARED_HIGH_PRIO(SH) 发生了堵塞。

2、对每个表加入到table cache,并且打开表(调用open_table_from_share())

那么这种情况就和SHOW TABLE STATUS[like 'A']被堵塞的情况一模一样了,也是由于MDL 锁不兼容造成的。

分析梳理

有了前面的分析那么我们可以梳理这个故障发生的原因如下:

有一个在B表上长期未提交的DML
语句会在innodb层对B表某些数据加innodb row lock。

由步骤1引起了CREATE TABLE A AS SELECT B的堵塞
因为RR模式下SELECT B必然对B表上满足的数据上锁,因为步骤1已经加锁所以触发等待,STATE为sending data。

由步骤2引起了其他语句的堵塞
因为CRATE TABLE A AS SELECT B在A表建立完成之前会上MDL_EXCLUSIVE(X),这把锁会堵塞其他全部的关于A表的语句,包括DESC/SHOW TABLE STATUS/USE DB(非-A) 这种只上MDL_SHARED_HIGH_PRIO(SH)MDL LOCK 的语句。STATE统一为Waiting for table metadata lock。

模拟测试

测试环境:

5.7.14

GITD关闭

RR隔离级别

使用脚本:

Mysql解决USE DB堵塞详解

步骤如下:

session1 session2 session3 session4------use test;---use test;begin; delete from b;------------use test;create table a asselect * from b;(由于b表innodb row lock堵塞)------------show table status like 'a';(由于a表MDL LOCK堵塞)------------use test(由于a表MDL LOCK堵塞)

最后我们看到的等待状态如下:

Mysql解决USE DB堵塞详解

这样我们就完美的模拟出线上的状态,如果我们杀掉session1中的事物,自然就全部解锁了,让我们再来看一下performance_schema.metadata_locks中的输出:

Mysql解决USE DB堵塞详解

我们可以看到如上的输出,但是需要注意LOCK_TYPE: SHARED它不可能堵塞LOCK_TYPE: SHARED_HIGH_PRIO(可以参考附录或者我以前写的MDL LOCK分析的文章)如上文分析这里实际上是做了升级操作升级为了MDL_EXCLUSIVE(X)。

总结

RC模式下虽然CREATE TABLE A SELECT B中B表不会上任何INNODB ROW LOCK但是如果B表非常大那么A表也会处于MDL_EXCLUSIVE(X)保护下,因此也会触发USE DB\SHOW TABLE STATUS等待的情况。

如果打开GTID不能使用CREATE TABLE A SELECT B这样的语句。

对于DML/DDL混用的系统一定要注意并发,就像本例中如果注意到高并发下的情况可以想办法避免。

这个案列再次说明了长期不提交的事物可能引发悲剧,所以建议监控超过N秒没结束的事务。

附录

MDL LOCK TYPE

Mysql解决USE DB堵塞详解

兼容性矩阵

Mysql解决USE DB堵塞详解

等待队列优先级矩阵

Mysql解决USE DB堵塞详解

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Mysql解决USE DB堵塞详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Oracle中redo日志堵塞怎么解决

OracleRedo日志堵塞解决方法Redo日志堵塞会影响数据库性能,需要及时解决。造成堵塞的原因包括日志文件空间不足、磁盘性能不佳、应用写入负载过高、表和索引结构更改以及备用数据库同步延迟。解决方法包括:增加日志文件空间、优化磁盘子系统、调整应用写入负载、优化表和索引结构以及调整备用数据库同步延迟。还建议启用FlashbackDatabase、使用logminer分析日志并定期监视日志使用情况。
Oracle中redo日志堵塞怎么解决
2024-05-13

linux消息队列堵塞如何解决

在Linux中,可以使用以下方法解决消息队列堵塞的问题:1. 设置非阻塞模式:在打开消息队列时,通过设置O_NONBLOCK标志可以将消息队列设置为非阻塞模式。这样,当消息队列为空时,读取操作将立即返回,而不是一直等待有新的消息到达。2.
2023-10-10

如何解决RabbitMq消息队列Qos Prefetch消息堵塞问题

本篇内容介绍了“如何解决RabbitMq消息队列Qos Prefetch消息堵塞问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Conne
2023-06-29

阿里云服务器网络堵塞原因及解决方案

在使用阿里云服务器的过程中,我们可能会遇到网络堵塞的问题,这可能会导致服务器的响应速度变慢,甚至完全无法访问。那么,是什么原因导致了阿里云服务器网络堵塞呢?又有哪些解决方案呢?本文将为您详细解答。原因分析:服务器带宽不足:如果阿里云服务器的带宽不足,那么在大量用户同时访问服务器时,网络流量就会超载,从而导致网络堵
阿里云服务器网络堵塞原因及解决方案
2023-10-30

阿里云轻服务器负载堵塞原因、解决方法及预防措施

在云计算环境中,服务器负载堵塞是一个常见的问题,特别是在阿里云轻服务器中,由于其规模庞大和用户需求的多样化,可能会出现负载堵塞的现象。本文将详细解释阿里云轻服务器负载堵塞的原因,提供解决方法以及预防措施。一、阿里云轻服务器负载堵塞的原因系统负载过高:当服务器的CPU、内存、磁盘等资源被大量占用时,系统负载会急剧增
阿里云轻服务器负载堵塞原因、解决方法及预防措施
2023-11-05

MySQL insert会阻塞update怎么解决

这篇文章主要介绍“MySQL insert会阻塞update怎么解决”,在日常操作中,相信很多人在MySQL insert会阻塞update怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL i
2023-07-05

详解mysql跨库查询解决方案

本文主要介绍了mysql跨库查询解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

MySQL慢查询以及解决方案详解

目录一、前言二、慢查询2.1 什么是慢查询?2.2 慢查询配置1、慢查询日志2、未使用索引是否开启日志3、慢查询时间设置4、慢查询路径三、慢查询日志分析3.1 mysqldumpslow工具四、慢查询解决方案4.1 索引失效4.2 SQL语
2023-05-05

编程热搜

目录