上篇关于MySQL BUG多不靠谱的问题,吸引了1000多的读者,有读者私信咋办,公司就要用MySQL也切不到PostgreSQL上,可MySQL bug多指望ORACLE是没戏了,怎么才能用上靠谱的MySQL.
今天咱们继续还是阿里云的宋利兵,宋老师解决了一个MySQL存在的大事务问题,今天我们来详细说说。说这个问题前还的说那个外国的MySQL专家的这篇文章。
原文链接:(点击不开的,需要复制链接在浏览器中打开页面) https://jfg-mysql.blogspot.com/2025/05/interesting-binlog-optimization-in-mariadb.html
MySQL的大事务问题
这里我就不翻译了,我总结一下这位“法国”加拿大MySQL专家对于MySQL的“吐槽”。
在使用行级复制的时候,我们难免遇到大事务,而大事务如果较大会导致超过了binlog_cache_size 的设置,最终产生磁盘的临时文件,而这个临时文件可是要跟着你的 binlog 文件的,这一个过程会占用磁盘空间,占用磁盘空间不怕,而更可怕的事会导致其他的事务提交慢,阻塞其他事务,产生MySQL的事务提交卡顿。
那么我们的开源MySQL管这个事情了吗? 当然他们不管开源的MySQL BUG多,性能差着不就是ORACLE要的吗,谁让人家是世界前五的云厂商。
在文章中这位Jean-François Gagné。(让先生 法语发音)提交了 MySQL Bug #118332 请求官方考虑引入该优化。同时文章中又提出了,这个问题阿里云的MySQL专家 宋利兵 宋老师已经有解决方案了,且用到人家的产品中去了。
这也就是说,阿里云的RDS MYSQL没有这个BUG,开源的你就用去吧,一用一个不吱声倒霉去吧。
image
我有幸请到了宋老师,宋利兵宋老师 MySQL老粉都知道,啥不知道宋利兵宋老师,你也配叫MySQL的Fans. 在很久很久年前,我还听过3306 Pai,吴丙锡吴老师请宋利兵宋老师在线 MySQL课堂给大家普法 MySQL innodb cluster的原理那时可是 MySQL 5.7,我依稀记得当时宋老师是 ORACLE 中国区负责 innodb cluster 集群的核心开发负责人。
这多少年过去了,宋老师还是持续优化MySQL,所以能人到哪里哪里的产品就牛逼,阿里云的RDS MYSQL 怎么就比你 线下的MYSQL强百倍,知道为什么了吧,牛逼的人在人家阿里云改造 MySQL了。
宋老师把核心对这个问题的改造的资料给我了,我凭着我MySQL这么多年的三脚猫功夫来稍微的解释解释。(其实是抄人家的材料)
宋老师资料
由于Binlog的串行写入机制,大事务不仅自身写入Binlog缓慢,还会阻塞其他事务提交。本功能优化了大事务提交时的Binlog写入机制,使提交速度不再受Binlog Event数量影响,始终保持高效。本功能解决了以下典型问题:
超大事务阻塞实例,导致其他事务无法及时提交。
大事务引发大量IO消耗,造成IO资源耗尽并拖慢查询等业务。
大事务导致小事务执行变慢,引发活跃连接激增和性能抖动,严重时可能触发雪崩效应导致实例不可用。
频繁执行大事务持续引发业务流量的性能抖动。
解决方案:
新建实例:Binlog Cache Free Flush功能默认开启。
存量实例:通过设置全局系统变量loose_binlog_cache_free_flush可开启该功能,参数修改后立即生效,无需重启实例。
相关参数:
loose_binlog_cache_free_flush_limit_size:开启Binlog Cache Free Flush功能后,当事务的Binlog超过该参数值,提交时会将Binlog Cache临时文件转为Binlog正式文件。默认值:256 MB,取值范围: 20971520~18446744073709551615 (单位:字节)
当MySQL实例执行大事务时,慢查询日志可能记录到某些本应快速完成的语句(如COMMIT)出现异常延迟。
阿里云原图
原因是另一个线程的大事务因Binlog串行写入机制导致资源竞争。大事务不仅自身写Binlog耗时较长,还会阻塞其他事务的Binlog提交,引发全局串行化延迟。
运行sysbench oltp_write_only时,在每5秒执行一次产生512 MB Binlog的大UPDATE操作后,观察到以下现象:
每次大UPDATE提交时,TPS(每秒事务数)剧烈下降。
抖动时长与Binlog大小正相关:事务产生的Binlog越大,对其他业务的延迟影响越显著。
下图直观的展示了大事务对线上运行业务的影响。
阿里云原图
UPDATE相关操作:
CREATE TABLE t_large (a INT, b LONGTEXT) ENGINE = InnoDB;# 插入一行数据包含256 MB文本,UPDATE时产生的Binlog events是512 MB。
INSERT INTO t_large VALUES (1, repeat('a', 256000000)); UPDATE t_large SET a = a + 1;
优化后的效果
TPS稳定性显著提升:
优化前:每5秒一次的大UPDATE导致TPS剧烈波动。
优化后(橙色线):大UPDATE对TPS的影响几乎消除。
橘黄色的线是优化后的
延迟无明显波动:
不同大小的UPDATE操作对时延的影响不再显著(橙色线为优化后)。
即使Binlog Events超过512 MB,其他事务提交的延迟未受明显干扰。
数据库主从延迟
一句话总结,宋老师如何解决这个问题的核心思想
让Binlog cache的临时文件变成最终的binlog文件,而不是复制到binlog文件中。这样在文件头部预留空间用于存放binlog文件头与头部events ,且预估end_pos,提交阶段直接可以将这些数据,转换为binlog的文件,最终优化大事务中的mysql的稳定性和减少数据主从复制延迟的问题,且还可以降低系统的I/O压力,减少阻塞其他事务。
开源的MySQL啥时候解决问题? 2030年吧,应该能解决! 现在咋办,公司开发垃圾就写大事务,那不行你就找 宋老师吧 ! 着急的MYSQL RDS 至少解决了这个大事务不稳定和主从延迟的问题,不信你就试试,当然这只是人家宋老师的优化和改造的冰山一角。