mysql元数据死锁日志_这个未修复的MySQL 5.7死锁Bug,你知道么?
破产码农
IT圈最会讲故事的网红 · 南山彭于晏
最近在生产上变更时遇到从机死锁的问题。表现的现象为:同一张的表的DROP TABLE操作进入了同一组。而由于并行复制,并且从机提交顺序需要保证与主机一致,因此产生了死锁。
从上图可以看到SQL语句DROP TABLE IF EXISTS z对应的二进制日志中的last_committed值都为3,也就是他们处于同一组。
若这时发生Worker Thread 2先执行,且要求从机提交顺序与主机一致,那么Worker Thread 2提交前会一直等待Worker Thread 1完成,而由于Worker Thread 2已经执行了DROP TABLE操作,Worker Thread 1无法获得元数据锁去执行删除同样的表z,因此产生经典的AB-BA死锁。
现在要解决这个问题,主要是思考:为什么DROP TABLE IF EXISTS z会进入了同一组提交队列中。
可以肯定的是,这的的确确是一个显而易见的Bug。而由于之前对组提交代码相对比较熟悉,个人第一时间的反应这应该不是组提交那块代码的Bug。
后来同事反馈是由于使用gh-osc进行表结构变更时,工具会执行类似执行LOCK TABLES t WRITE,z WRITE多表锁定语句,从而引起死锁。
在有了上述线索后,就比较好定位死锁问题了。
死锁问题分析与定位
执行命令LOCK TABLES t WRITE,z WRITE会对表t、表z加上表级别的SHARED_NO_READ_WRITE的元数据锁。
这个元数据锁是在SQL引擎层的,对应源代码mdl.cc,并不是InnoDB引擎层的行记录锁。
接着,尝试测试在执行完上述SQL命令后,接着去执行DRO TABLE IF EXISTS z,这时发现对应表z上的表级别元数据锁已释放。
这也符合预期,毕竟删除表z,同时释放已持有的元数据锁,这是正常逻辑。
然而,在深入分析源码后,发现使用LOCK TABLES命令先去锁表,再去删除表,和普通的删除表操作,两者在释放元数据锁的时间是不一样的。
先来看普通的DROP TABLE操作,其内部的流程如下图所示:
正常的删除操作在完整提交后,才释放元数据锁。
但若通过命令LOCK TABLES现在去锁住两张表,接着再删除其中一张表,如我们演示的表z,则内部的流程如下图所示:
这时会发生在完整提交前就释放了表z的元数据锁。若这时有其他线程执行DROP TABLE IF EXISTS z的操作,则有可能进入到orderd_committed流程,从而导致两个DROP TABLE在同一提交组的可能。
若想要在自己的测试环境中更为容易的模拟出DROP TABLE在同提交一组的环境,同学们可以调整如下参数,:
binlog_group_commit_sync_delay = 1000000
binlog_group_commit_sync_no_delay_count = 8
若是源码调试,可以定位文件sql_table.cc,定位到函数mysql_rm_table设置断点。
内核层Bug修复方案
发现这个Bug后,姜老师花时间研究看了下源码。其实从代码逻辑上看是没有问题的,只是在从机回放的时候存在问题。所以,从严格意义上看,这个并不算Bug。只能说是一种不完美的缺陷。
然而,对于业务来说,这是的的确确的Bug。从机死锁,主从延迟,会导致各种严重的问题。
若将参数slave_preserve_commit_order设置为0,即不要求主从二进制日志顺序一致,可以规避上述问题,主从数据依然保证一致。但这不是完美的解决方案。
这个Bug的修复还真有些棘手,尝试想了很多方法,总没有特别好的思路。
例如参考之前DROP USER IF EXISTS,如果没有实际表删除,则不记录二进制日志。然而,这个方法并不好,官方最近版本DROP USER IF EXISTS无论是否有删除用户操作,也都记录二进制日志。
同样,若将上述thd->mdl_context.release_all_locks_for_name这行注释掉,那么会存在DROP TABLE z后,表z的元数据锁依然存在,只有当执行完命令UNLOCK TABLES才完全释放元数据锁。
这种方式,虽能避免上述问题,但还是有些实现上的不完美。
神奇的MySQL 8.0
这时看了下MySQL 8.0的源码mdl.cc,发现相对5.7做了比较大的重构。扫了下代码,无意中发现多了一种新类型的元数据锁——TABLESPACE元数据锁。
接着测试验证发现8.0并不存在5.7上述的Bug!!!因为DROP TABLE IF EXISTS只释放TABLE元数据锁,并不释放TABLESPACE元数据锁。
那么当线程2执行同样命令时,则由于TABLESPACE元数据存在,会触发等待,因此也不存在同一组中存在相同的DDL。
至于为什么要引入TABLESAPCE的元数据锁,可看官方的Worklog:https://dev.mysql.com/worklog/task/?id=7957
复盘与思考
从数据库角度看,这并不是MySQL内核层的死锁Bug。
这是因为使用gh-osc工具,引发的从机并行复制潜在的Bug。从概率上看也并不一定100%可以复现。
在翻看gh-osc工具源码中,也发现已经有用户提出从机死锁问题。官方也计划在1.1版本中修复。主要是让已经删除的表,不再有多次删除的可能。
当然,非要说是内核Bug,其实也是。毕竟二进制日志中last_committed值是错误的,从而引发从机并行回放的死锁。
这个Bug并不好很直观的进行修复。不过在8.0中,由于引入了TABLESAPCE元数据锁,反而弯打正着地解决了这个Bug。
好在这个Bug并非致命,发生概率非常小。若不使用gh-osc,则99%的概率不会遇到。若你有遇到,不妨留言,看看同学们是怎么解决这个的呢?
-----------------------
公众号:破产码农(ID:manongBR)
B站:Jiang老师
微博:破产码农
知乎:破产码农
mysql元数据死锁日志_这个未修复的MySQL 5.7死锁Bug,你知道么?相关推荐
- mysql 删除过期日志_【转】对mysql日志进行操作的总结包括 启用,过期自动删除 等...
近段时间一直在研究mysql的日志系统,在网上看了N多mysql日志操作的文章,但都过于零乱,为了让自己以后不再搞忘,特作出以下总结: 1. 以前我错误的认为mysql的日志可以恢复到任何时间的状态, ...
- c语言连接数据库例子,c语言操作mysql数据库小例子_互帮互助(C language MySQL database operation example _ mutual help).doc...
这是精心收集的精品经典资料,值得下载保存阅读! c语言操作mysql数据库小例子_互帮互助(C language MySQL database operation example _ mutual h ...
- mysql数据库binlog日志截断报错,导致mysql主从同步失败故障排查
mysql数据库binlog日志截断报错,导致mysql主从同步失败故障排查 Got fatal error 1236 from master when reading data from binar ...
- 查看mysql数据库的死锁日志_【MySQL】mysql死锁以及死锁日志分析
1.死锁的概念 死锁:死锁一般是事务相互等待对方资源,最后形成环路造成的. 对于死锁,数据库处理方法:牺牲一个连接,保证另外一个连接成功执行. 发生死锁会返回ERROR:1213 错误提示,大部分的死 ...
- mysql排插问题_手把手教你分析 MySQL 死锁问题
原标题:手把手教你分析 MySQL 死锁问题 前言 前几天跟一位朋友分析了一个死锁问题,所以有了这篇图文详细的博文,哈哈~ 发生死锁了,如何排查和解决呢?本文将跟你一起探讨这个问题 准备好数据环境 模 ...
- mysql数据库崩溃日志_我们崩溃并丢失了所有基本数据日志。 我们哪里错了?
mysql数据库崩溃日志 放松,没有人迷失森林. 他们失去的是大量必要的数据日志. 此处的主题公司称为TheCompany. 发现问题的开发人员是Bob. 在本文中,我想讨论软件开发中的人为错误以及针 ...
- 如何linux查看mysql目录下日志_测试人员如何在linux服务器中查询mysql日志?
测试工程师在测试软件的过程中,流程往往是先接口测试,接着就是功能性测试.在做功能性测试的时候,往往有这么一个工作场景,就是出现错误后,我们怎么快速排除数据库报错. 举例某个电商网站,当我们文本框中输入 ...
- mysql grep 提取错误日志_详解grep获取MySQL错误日志信息的方法
为方便维护MySQL,写了个脚本用以提供收集错误信息的接口.这些错误信息来自与MySQL错误日志,而 通过grep mysql可以获取error-log的路径. 以下是全部相关代码: #!/usr/b ...
- mysql 刷新二进制日志_使用binlog日志恢复MySQL数据库删除数据的方法
binlog日志简介: binlog 就是binary log,二进制日志文件,这个文件记录了MySQL所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间. b ...
最新文章
- Algs4-1.1.13编写一段代码,打印出一个M行N列的二维数组的转置(交换行和列)
- Java 线程池中的线程复用是如何实现的?
- ASP.NET MVC中使用AJAX(XMLHttpRequest、Microsoft AJAX Library......)
- 【物联网】 ESP8266 Ubuntu开发环境的搭建
- MySQL主从复制虽好,能完美解决数据库单点问题吗?
- Android 升级到android studio 2.2项目死活run不起来
- 指数级暴增、复杂场景下,揭秘百度云原生湖仓架构等系列数据产品
- XSD(XML Schema Definition)学习笔记
- 华大基因辟谣“基因编辑58个婴儿”;苹果发布头戴式耳机AirPods Max;Debian 10.7发布|极客头条...
- Hbase数据结构+hbase shell基本语法
- 小学计算机应用到英语课教案,信息技术在小学英语教学中的应用
- 2021年下半年软考真题软件设计师真题答案(上午题)
- 手机连接USB通过宽带免费上网
- 1946年第一台公认电子计算机,1946年诞生的世界上公认的第一台电子计算机是()。...
- 解决Chrome浏览器主页被篡改(劫持)hh899899.com的问题
- at命令不生效 linux_linux中at命令详解
- echarts学习笔记
- 专家 | 黄道丽:网络安全漏洞披露规则及其体系设计
- X230网卡驱动安装总不成功的问题
- kotlin混淆后mapping定位