查看原文
其他

MySQL 8.0,二进制日志的一大改进!

破产码农 InsideMySQL 2022-10-13

        

破产码农

IT圈最会讲故事的网红 · 南山彭于晏

很多同学吐槽 MySQL 数据同步没有采用物理复制,而是使用逻辑的二进制日志,因此抱怨主从数据同步较慢。

然而,随着基于 WRITE SET 并行复制技术推出,以及 MySQL 8.0 快速加列功能的诞生,只要架构设计得当,MySQL 主从数据延迟的问题几乎已不存在。

相反,姜老师在过去的文章中,一再强调二进制日志是 MySQL 数据库成功的关键。如:移除MySQL Binlog?亲,你根本不懂MySQL呐~~~

逻辑日志意味着 MySQL 中的数据不会是一个终点,它可以方便地流向用户想要使用的业务场景。

例如在 MySQL 数据库的数据可以准实时地推送给 ElasticSearch 做检索,发送给 Spark 做推荐分析,等等。

相比,Oracle、Microsoft SQL Server、PostgreSQL,他们这方面就明显弱很多。

因为,物理日志不好实现异构系统的数据同步。

当然,物理日志 vs 逻辑日志的问题,之前都已分析过。

今天讨论的重点是 MySQL 8.0 中关于二进制日志的改进。


1

二进制日志的元数据


通过二进制日志,可以非常容易捕获 MySQL 数据库中的变更,从而推送给其他数据平台。

但是,二进制日志中是否有存储每条记录的元数据信息呢?例如:

  1. 每条记录对应的库名是什么?

  2. 每条记录对应的表名是什么?

  3. 每条记录中每个列的类型是什么?

  4. 每条记录中每个列的名称是什么?

  5. 每条记录中,哪个列是主键?

可以通过命令mysqlbinlog来解析二进制日志,回答上面的问题:


上面的这张图显示了通过命令 mysqlbinlog 对二进制日志 binlog.000001 的解析结果。

可以看到类型为 Table_map 的二进制日志 event ,可以捕获这条记录对应的库名和表名。

类型为 Write_rows 的二进制日志 event ,表明这条记录是由 INSERT 操作记录的二进制日志。

下面的的 @1=3 /* INT meta=0 nullable=0 is_null=0 */ 表示插入记录的列 1 值为 3 ,类型是 INT 。

也就是说,对于上面的 5 个问题,其中 3 个二进制日志是有保存对应信息的。

然而,二进制日志中并没有存储每条记录每个列的名称,以及哪个列是主键的元数据信息

这些信息对于 DTS(Data Transfer Service) 服务来说,非常关键。

因此,如果通过 MySQL 二进制日志实现 DTS服务,需要额外的手段获取这些信息。

业界开源 DTS 做得比较好的是 Maxwell 。

简单易用,用 JSON 描述二进制日志中每条记录的信息,并发送到 Kafka :


通过上面的例子,可以看到 Maxwell 可以捕获每条记录的列名。这里是 id、m、c、comment。

更重要的是, Maxwell 还会记录主键值和主键对应的列。

可以发现,上面的例子中,主键是由列 id、c 组成的。

快速扫了下 Maxwell 的源码,发现 Maxwell 实现原理是去查询表 information_schea.COLUMNS ,从而获取这些元数据信息:


虽然 Maxwell 曲线实现了获取列名和主键的信息,但 MySQL 8.0 版本后,就无需这么复杂的实现了。

因为,上面的元数据信息,将被直接写入到二进制日志。


2

MySQL 8.0 二进制日志增强


MySQL 8.0 版本允许将每条记录的列名和主键信息存储到二进制日志的 Table_map event 中。

这个新特性默认关闭,需要通过将参数 binlog_row_metadata 设置为 full 才能打开此特性:

mysql > SET GLOBAL binlog_row_metadata = full;

之后,再通过命令 mysqlbinlog ,再加入新参数 --print-table-metadata 就能打印出每条记录的列名和主键信息了:


显然,这个特性会增大二进制日志的容量,但如果计算下 Table_map event的增长,其实会发现只从47字节增长为了65字节,开销并不是特别大。

当然,如果你表字段非常多,那么增长的幅度就会相对比较大了。

不过,当二进制日志包含了每条记录的值和元数据信息, DTS 就变得非常 easy 了。

更重要的是,每次表结构发生 DDL 变更时,也不用进行额外的处理。


3

总结


今天的文章介绍了 MySQL 8.0 对于二进制日志的一个改进。

通过设置参数 binlog_row_metadata 为 FULL ,可以在二进制日志中包含每条记录的所有元数据信息。

虽然对于二进制日志存储来说,会增加一定的存储开销。

但对于异构系统之间的数据同步来说,这个特性会非常有用。

最后,姜老师想说的是,都2021年了,你还不升级到 MySQL 8.0 这个伟大的版本么?

伟大航路,即将启航~~~


直播预告


每周五、六,不定期直播,分享技术干货


IMG群是码农的交流社区,IMG微信群交流内容包括但不限于技术、经济、军事、八卦等话题。欢迎有态度的码农们加入IMG大家庭。
IMG目前有少林群、武当群、峨眉群、华山群、M悦会(高端VIP群)
仅限码农入群,猎头或其他行业勿加,入群请加姜老师个人微信 82946772,并备注:码农入IMG群
-----------------------
公众号:破产码农
视频号:破产码农
抖音号:破产码农
B站号:姜老师带你飞
长按下图二维码关注,将感受到一个有趣的灵魂,每篇文章都会有新惊喜。

          

往期推荐


01集 | MySQL崛起:缘起


02集 | MySQL崛起:起飞


MySQL性能提升40%的AHI功能,你知道么?


一张图看懂程序员的这一生,看到最后我哭了......


从今天起,用好 JSON 数据类型!


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存