mysql数据库杀掉堵塞_Mysql解决USE DB堵塞详解

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

故障描述

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

MYSQL 5.6.16

RR隔离级别

GITD关闭

表现如下:

use db不能进入数据库

show table status不能查询到表信息

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

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

201712241415507.png

故障信息提取

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

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:

//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监测方法如下:

201712241415508.png

一、关于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)。

方式一

201712241415519.png

方式二

2017122414155110.png

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

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

兼容性:

2017122414155111.png

阻塞队列优先级:

2017122414155112.png

其被堵塞的条件除了被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) ,然后进行实际测试不出所料确实是这样的如下:

方式一

2017122414155113.png

方式二

2017122414155114.png

这里比较遗憾在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) 如下:

方式一

2017122414155115.png

方式二

2017122414155216.png

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

其兼容性如下:

2017122414155217.png

显然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)不兼容。如下:

方式一

2017122414155218.png

方式二

2017122414155219.png

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

六、为何use db也会堵塞?

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

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

方式一

2017122414155220.png

方式二

2017122414155221.png

可以看到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隔离级别

使用脚本:

2017122414155222.png

步骤如下:

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堵塞)

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

2017122414155323.png

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

2017122414155324.png

我们可以看到如上的输出,但是需要注意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

2017122414155325.png

兼容性矩阵

2017122414155326.png

等待队列优先级矩阵

2017122414155327.png

本文标题: Mysql解决USE DB堵塞详解

本文地址: http://www.cppcns.com/shujuku/mysql/215579.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java拦截器项目应用_使用拦截器分析Java EE应用程序的性能下降/提高

java拦截器项目应用在开发具有某些性能要求的Java EE应用程序时,必须在每个发行版之前验证是否满足这些要求。 您可能会想到,哈德森的一项工作每天晚上在某些特定的硬件平台上执行一系列测试测量。 您可以检查已实现的时间并将它们与给定的要求进行比较…

iis web.config 配置 经典模式_django部署在iis下,webconfig错误

django部署在iis下,webconfig错误错误原因:iis7以后,web.config管理机制更安全了默认情况下,会锁住配置项,不许修改怎么办?如何求解以上问题呢?D:django_websiteshello>%windir%C:Windows 不…

如何在Java中验证电话号码(正则表达式+ Google libphonenumber)

关于如何在不同国家(例如美国,美国)使用Java验证电话号码的快速指南。 带有正则表达式和Google libphonenumber API的示例程序。 1.简介 在本教程中,我们将学习如何在java中验证电话号码 。 这主要是为了验证美国和印度的国家/地…

mysql该账户已存在_mysql 查看函数的所属用户和已存在的函数

复现方式:Delete FROM user Where Usertest and Host%;flush privileges;修复流程:1.用root用户删除两个函数,语句分别为DROP FUNCTION IF EXISTS currval;DROP FUNCTION IF EXISTS nextval;2.然后用程序用户(sharding_slave)创建函数&#x…

joo工作流_不要错过使用jOOλ或jOOQ编写Java 8 SQL单行代码的机会

joo工作流越来越多的人通过为他们的业务采用功能性编程来赶上我们平台的最新更新。 在Data Geekery ,我们将Java 8用于jOOQ集成测试,因为将新的Streams API与lambda表达式一起使用使生成临时测试数据变得非常容易。 但是, 我们并不认为JDK提…

session mysql登录实现_PHP+MYSQL+MYSQL+SESSION实现用户登录的实例

这是我写的用户登录界面。session_start();include(menu2.php);require(configywcl.php);//加载配置文件require(functions.php);?>请登录系统if ($username){$passwordmd5($password);$sql"select * from user where username$username and password$password";…

使用OpenSSL加密,使用Java解密,使​​用OpenSSL RSA公钥

抽象 在2017年,我撰写了一个由三部分组成的系列文章,内容涉及选择最佳的哈希和加密算法。 在对该系列进行研究时,我学到了很多有关哈希和加密的知识。 我学到的最重要的事情是,尽管我必须对如何使用最安全的算法进行自我教育&…

axture动画原型制作_Axure制作原型-基础操作

产品原型从类型可以分为手稿、线框图、低保真、高保真几种效果,在制作的时候分为不同场景来决定我们的输出物类型。比如在会议中为了快速的确定产品规划方向,迅速的记录及表达出当前灵感的碰撞,这个时候通常使用手稿的形式快速绘制&#xff0…

有效Java第三版的源代码已更新为使用较新的功能

那些已经阅读了有效Java 第三版的人可能知道与该书相关的源代码可以在GitHub上获得 。 jbloch / efficiency-java-3e-source-code项目拥有1700多个星星,截至撰写本文时,它已被分叉了近800次。 在有效Java的第三版中, Java的版本主要是JDK 8&a…

mysql 远程连接取消权限_MYSQL远程登录权限设置

Mysql默认关闭远程登录权限,如下操作允许用户在任意地点登录:1. 进入mysql,GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY WITH GRANT OPTION;IDENTIFIED BY后跟的是密码,可设为空。2. FLUSH privileges; 更新Mysql为了安…

spring和spring_Spring WebApplicationInitializer和ApplicationContextInitializer的混淆

spring和spring我偶尔会混淆这两个概念-WebApplicationInitializer和ApplicationContextInitializer,并希望描述它们中的每一个,以便为我自己澄清它们。 我以前曾在这里写过有关WebApplicationInitializer的博客。 它仅在符合Servlet 3.0规范的Servlet容…

mybatis mysql demo_SpringBoot(入门Demo,整合mybatis,连接mysql)

1.简介SpringBoot提供一种固定的、约定优于配置风格的框架,使开发者更快地创建基于spring的应用和程序。可以高效的创建基于Spring的应用服务(SpringBoot不是对spring功能的增强,而是可以更快速使用spring)。为微服务spring cloud铺路,可整合…

HttpClient 4 API –获取状态码-getStatusLine()。getStatusCode()示例

在HttpClient API中获取状态代码的快速指南。 getStatusLine()。getStatusCode()示例和相关的错误。 1.简介 在这个非常快速的教程中,我将展示如何使用HttpClient 4获取和验证HTTP响应的StatusCode。 2. Maven依赖 要…

css table嵌套内部table不受外部影响_HTML+CSS网页一揽子(4)

CSS重要属性之浮动基本属性:float:left;左浮动float:right;右浮动float:none;不浮动(一般应用于覆盖既有浮动属性时使用)clear:both;清除浮动对其他元素带来的影响应用场景:(1)网站大的结构布局&#xff1a…

ejb构建_如何使用单例EJB和MBean构建和清除参考数据缓存

ejb构建在我的一个项目中,我需要使用EclipseLink作为ORM框架从Java EE 6 WebLogic环境中的多个源中加载参考数据。 由于我在Java EE世界中找不到与Spring YET的Cacheable相当的注释,因此我不得不编写自己的缓存解决方案。 尽管参考数据几乎不会随时间变化…

mysql ticks_【原创】C# 计时周期数(Ticks)在不同数据库上的实现

动手之前,先来看看 Ticks 在微软官方文档上的定义:注解一个计时周期表示一百纳秒,即一千万分之一秒。1 毫秒内有 10,000 个计时周期,即 1 秒内有 1,000万个计时周期。此属性的值表示自0001年1月1日午夜12:00:00 0:00:00 (公历日期…

在Spring Boot测试中使用Testcontainer进行数据库集成测试

在此博客文章中,我想演示如何在Spring Boot测试中集成Testcontainer以便与数据库一起运行集成测试。 我没有使用Testcontainers的Spring Boot模块。 如何与他们合作,我将在另一篇博客文章中进行介绍。 所有示例都可以在GitHub上找到 。 为什么要使用测试…

php模块安装 pdo_mysql_关于php插件pdo_mysql的安装

今天在做一个商城的连接的时候,需要MpDO验证。需要安装pdo_mysql模块,刚开始按照php扩展模块的安装按照这个安装ZIP,curl都成功了但是安装pdo_mysql却不行,在./configure --with-php-config/usr/local/php/bin/php-config是出现错误。如下che…

java8串行和并行的区别_垃圾收集器–串行,并行,CMS,G1(以及Java 8中的新增功能)...

java8串行和并行的区别4个Java垃圾收集器–错误的选择如何严重影响性能 在2014年,对于大多数开发人员来说,还有两件事仍然是个谜:垃圾收集和了解异性。 由于我对后者知之甚少,所以我认为我会对前者大吃一惊,尤其是因为…

python函数参数学习_python学习笔记-11.函数参数和返回值进阶

1. 函数参数和返回值的作用函数根据有没有参数以及有没有返回值,可以相互组合,共有4种形式:无参数,无返回值无参数,有返回值有参数,无返回值有参数,有返回值定义函数时,是否接收参数…