技术分享 | binlog 异常暴涨分析
你在学习数据库相关的知识吗?本文《技术分享 | binlog 异常暴涨分析》,主要介绍的内容就涉及到MySQL、数据库,如果你想提升自己的开发能力,就不要错过这篇文章,大家要知道编程理论基础和实战操作都是不可或缺的哦!
转载自 微信公众号:yangyidba
作者:高鹏
文章末尾有他著作的《深入理解MySQL主从原理 32讲》,深入透彻理解MySQL主从,GTID相关技术知识。
背景
这是一个朋友遇到的问题,他的现象大概如下(MySQL5.6):
某个binlog实际大小3g左右,实际设置大小应该是1g
其中包含一个大事务,但是最后一个事务是小事务
查看大事务的XID_EVENT('commit')时间和最后一个小事务XID_EVENT('commit')时间差值近15分钟
下面是他提供的依据:
mysqlbinlog -vv mysqlbinlog_file > mysqlbinlog_res.log grep -n -B 1 "COMMIT" mysqlbinlog_res.log > file.log tar zcf file.log.tar.gz file.log
通过结果可以看到大事务提交完成是binlog文件的行号是 392578997 ,往前推一个事务,
提交完成后的行号是 42614752 ,
期间相差3.2亿行,就是说这个事务总共写了3.2亿行的binlog
大事务提交的时间是12:54:12,Xid = 4103492840 ,结束的pos值是 2915555141
最后一个事务的提交时间13:08:43,Xid = 4104544654 ,结束的pos值是 2915740337
问题
为什么最后事务是小事务而不是最大的那个事务,为什么大事务束后没有切换binlog呢?
为什么最后一个小事务和大事务提交时间相差了15分钟之多呢?
实际上这些问题的原因我都在我的《深入理解MySQL主从原理 32讲》中说明了,有兴趣可以关注一下文末的课程。
好了下面我们来实际分析一下。
分析
一、提交流程图
这张图是《深入理解MySQL主从原理 32讲》中第15节的截取如下,当然这个图是基于MySQL 5.7.22 画的:

好了有了这张图我们继续分析。
二、为什么大事务会包含在一个binlog里面
如图中第10步我们可以看到在flush队列的事务Event都写到binlog(不是fsync)后才会进行binlog切换的标记,言外之意就是不管有多大的事务那么都要等到写完binlog后才进行切换标记的设置。因此大事务总是在一个binlog里面。
三、为什么最后事务是小事务而不是最大的那个事务
事实上在第10步中我们只是设置了切换标记而已,实际的切换会等到本事务所在的commit队列都提交完成后才会进行binlog的切换,具体就是参考第28步。
在这个期间会有2个原因导致大事务并不是binlog的最后一个事务:
对于flush队列而言,大事务可能包含在队列中的某个位置,队列后面可能包含小事务。
对于sync队列而言,大事务的提交会在sync阶段耗费很多时间,如果我们假设为30秒,那么在这30秒内其他新的事务是可以进入新的flush队列的,也能够进行写binlog(不是fsync)的操作。
因此线上有压力的库,binlog的最后一个事务通常不是大事务。
四、为什么最后一个小事务和大事务之间XID_EVENT(commit)时间相差了15分钟之多
首先这个问题有两种可能:
对于自动事务提交,那么XIDEVENT会是命令发起的时间,因此更容易出现这种情况,后面会使用这种情况进行证明。对于显示开启事务‘begin commit’,那么XIDEVENT会是commit命令发起的时间,但是如果fsync时间足够久那么也会出现这种问题。这种情况不容易测试,因为需要足够大的数据,人为测试很耗时。下面就是这种情况出现的原因。
关于以上两种情况的这种差别我已经在我的《深入理解MySQL主从原理 32讲》中第12讲、第14讲说明了原因。
这里我们就假定大事务的提交在sync阶段花费了大约15分钟,那么如下:

如果T5和T2之间相差15分钟左右,那么这期间进来的这些小事务依然保留在本binlog里面(因为还没切换29步才切换),那么就有可能看到小事务和大事务之间XID_EVENT(commit)时间相差很大了。
实际上在5.7中上面两种情况都很可能都会生成同样的last commit,因为这个时候由于大事务fsync的堵塞第22步更改last commit的操作是不能进行的。
五、在5.7.22中测试
整个测试过程必须卡准大事务进行提交这个时间点,我的参数设置如下:
max_binlog_size:1048576,设置较小的binlog大小方便测试。
binlog_group_commit_sync_delay:1000000,将本参数设置为1秒,用于拖长整个提交流程便于测试,但是实际上大事务的fsync操作可能会更加耗时。
binlog_transaction_dependency_tracking:COMMITORDER,这是默认的配置,为了更好的证明我们前面生成同样的last commit的结论,避免writeset的干扰。
并且我在我的debug环境中设置了断点MYSQLBINLOG::ordered_commit,用于更好的测试,否则自动提交事务的情况下非常难确认事务到底什么时候进行提交的。
最后我们不使用通过‘begin commit’显示的开启事务,因为这样XIDEVENT的时间是commit命令发起的时间,也就不太容易重现案例中的这种XIDEVENT大事务和小事务时间相差很大现象。但是实际上如果事务足够大也是可以的,因为在大事务如案例中有几亿的数据那么这个事务的sync过程会非常缓慢,但是我的测试环境没有那么多的数据,为了让测试效果更加明显因此使用自动提交,这样所有的Event都是命令发起的时间。
首先我做了一张较大的表有70W的数据,然后删除整个表的数据,显然这个事务的binlog会大于1M。下面这个表格就是操作流程:

只要T4-T1的时间足够长那么就可能出现案例中的情况。如下是我的binlog的截图,可以看到binlog.000017为3.5M左右:

下面是我解析binlog.000017的最后部分内容,我们可以发现最后两个事务均是小事务,大事务并不是最后一个事务如下:
### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ ### DELETE FROM `testmts`.`testnnn` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ # at 3626617 #190804 22:56:10 server id 413340 end_log_pos 3626648 CRC32 0xfc5b79e7 Xid = 143 COMMIT/*!*/; # at 3626648 #190804 23:02:26 server id 413340 end_log_pos 3626713 CRC32 0xa2399157 GTID last_committed=0 sequence_number=2 rbr_only=yes /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/; SET @@SESSION.GTID_NEXT= 'cb7ea36e-670f-11e9-b483-5254008138e4:191'/*!*/; # at 3626713 #190804 23:02:26 server id 413340 end_log_pos 3626788 CRC32 0x555fb49d Query thread_id=4 exec_time=0 error_code=0 SET TIMESTAMP=1564930946/*!*/; BEGIN /*!*/; # at 3626788 #190804 23:02:26 server id 413340 end_log_pos 3626838 CRC32 0xec0a4316 Table_map: `testmts`.`tm10` mapped to number 149 # at 3626838 #190804 23:02:26 server id 413340 end_log_pos 3626878 CRC32 0x61c79d68 Delete_rows: table id 149 flags: STMT_END_F ### DELETE FROM `testmts`.`tm10` ### WHERE ### @1=10 /* INT meta=0 nullable=1 is_null=0 */ # at 3626878 #190804 23:02:26 server id 413340 end_log_pos 3626909 CRC32 0x2a9cd136 Xid = 154 COMMIT/*!*/; # at 3626909 #190804 23:02:26 server id 413340 end_log_pos 3626974 CRC32 0x06b081ec GTID last_committed=0 sequence_number=3 rbr_only=yes /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/; SET @@SESSION.GTID_NEXT= 'cb7ea36e-670f-11e9-b483-5254008138e4:192'/*!*/; # at 3
仔细观察你会发现 23:02:26和22:56:10之间相差了6分钟之多。然后我们来看看他们的last commit如下:
[root@mysqltest2 log]# cat -n log.log|grep last 11 #190804 22:56:10 server id 413340 end_log_pos 299 CRC32 0x47602f13 GTID last_committed=0 sequence_number=1 rbr_only=yes 2167349 #190804 23:02:26 server id 413340 end_log_pos 3626713 CRC32 0xa2399157 GTID last_committed=0 sequence_number=2 rbr_only=yes 2167368 #190804 23:02:26 server id 413340 end_log_pos 3626974 CRC32 0x06b081ec GTID last_committed=0 sequence_number=3 rbr_only=yes
我们发现如我们所述,它们的last commit是一致的。到这里我们全部的结论都得到证明。
六、注意
最后需要提醒一下,MySQL不要有过大的事务,我觉得大事务最大的危害在于会堵塞整个数据库其他事务的提交,这个在我的《深入理解MySQL主从原理 32讲》中已经多次提到,这里就不在赘述了。
最后推荐高鹏的专栏《深入理解MySQL主从原理 32讲》,想要透彻了解学习 MySQL 主从原理的朋友不容错过。
以上就是《技术分享 | binlog 异常暴涨分析》的详细内容,更多关于mysql的资料请关注golang学习网公众号!

- 上一篇
- 苹果电脑画流程图软件

- 下一篇
- 基于docker构建的thinkphp5框架环境
-
- 数据库 · MySQL | 6小时前 |
- MySQL无法启动?8个排查方法全解析
- 174浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- 主键与唯一键区别,如何选主键?
- 166浏览 收藏
-
- 数据库 · MySQL | 11小时前 |
- MySQL多表连接优化技巧与实战策略
- 221浏览 收藏
-
- 数据库 · MySQL | 22小时前 |
- MySQL排序优化与性能提升技巧
- 153浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL中WHERE与HAVING的区别详解
- 340浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL排序优化与性能提升技巧
- 368浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL连接池配置与优化方法
- 297浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQLGROUPBY使用技巧与常见问题
- 306浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL缓存优化技巧分享
- 392浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL安装到D盘教程及路径设置详解
- 279浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL缓存设置及查询作用解析
- 470浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 96次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 89次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 107次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 98次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 99次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览