开源一个 rust 的 mysql binlog parser

💡 原文中文,约27700字,阅读约需66分钟。
📝

内容提要

该文章介绍了MySQL的binlog解析以及一款新的基于Rust实现的binlog解析器。binlog是MySQL数据同步的基础,ROW类型是最优解。文章提供了解析库的地址和支持的事件类型。同时,还介绍了如何运行测试用例和解析json字段的方法。

🔎

延伸解读

为何选择 ROW 格式及解析器定位

文章指出 MySQL 支持 STATEMENT、ROW、MIXED 三种 binlog 格式,但 ROW 格式记录每行修改前后的完整内容,数据准确性更高,是数据同步行业的通用方案。目前主流解析库均针对 ROW 类型,而 mysql-binlog-connector-rust 同样聚焦于 Row Based Replication Events,使用异步 IO 实现,适合需要增量订阅、数据集成等场景的 Rust 开发者。

类型映射中的精度与符号处理

解析器将 MySQL 数据类型映射为 Rust 类型,但存在若干限制:CHAR/VARCHAR 因 binlog 不含字符集信息,仅存储二进制数据,需用户根据列元数据转换;UNSIGNED 数字列被解析为有符号数字,同样需用户自行处理符号;JSON 列默认存储二进制,但提供 JsonBinary 解析器可转为字符串。这些设计意味着使用者需结合表结构信息做二次处理。

事务压缩与不支持事件的处理策略

对于 MySQL 8.0 的 binlog-transaction-compression,解析器能识别 TRANSACTION_PAYLOAD_EVENT 并解压出内部事件,如用例所示。同时,对于暂不支持的事件类型,解析器会直接忽略,不影响其他事件的解析。这种容错策略降低了因未知事件导致解析中断的风险,但也意味着使用者需留意可能丢失某些事件信息。

测试与用例的实践提示

文章提供了基于 Docker 的测试环境搭建步骤,分别启动 MySQL 5.7 和 8.0 并配置 binlog 参数,通过环境变量指定连接信息。测试用例覆盖关闭和开启事务压缩的场景,并提示对于大事务可能需要增大 binlog_parse_millis 等待解析完成。此外,JSON 字段解析示例展示了如何将二进制 JSON 转为字符串,方便实际使用。

❓

Q&A

mysql-binlog-connector-rust 是什么?它支持哪些 MySQL 版本?

mysql-binlog-connector-rust 是一款用 Rust 实现的、使用异步 IO 解析 MySQL 的 Row Based Replication Events 的库。它支持的 MySQL 版本包括 5.6(测试版本 5.6.51)、5.7(测试版本 5.7.40)和 8.0(测试版本 8.0.31)。

为什么 binlog 解析通常选择 ROW 格式而不是 STATEMENT 或 MIXED?

尽管 MySQL 支持 STATEMENT、ROW、MIXED 三种 binlog 格式,但从方便性和数据准确性来讲,ROW 类型是最优解,也是行业的通用方案。ROW 格式的 binlog 以行的形式记录每个操作,提供详细的更改信息(包括修改前的旧值和修改后的新值),而不仅仅是 SQL 语句。目前所有主流的 binlog 解析库均是针对 ROW 类型。

mysql-binlog-connector-rust 支持哪些 binlog 事件类型?对于不支持的事件会怎么处理?

支持的事件类型包括:FORMAT_DESCRIPTION_EVENT、ROTATE_EVENT、PREVIOUS_GTIDS_LOG_EVENT、GTID_LOG_EVENT、QUERY_EVENT、XID_EVENT、XA_PREPARE_LOG_EVENT、TRANSACTION_PAYLOAD_EVENT、ROWS_QUERY_LOG_EVENT、TABLE_MAP_EVENT、WRITE_ROWS_EVENT_V1、WRITE_ROWS_EVENT、UPDATE_ROWS_EVENT_V1、UPDATE_ROWS_EVENT、DELETE_ROWS_EVENT_V1、DELETE_ROWS_EVENT。对于暂不支持的事件类型,解析器会直接忽略,并不影响对其他事件的解析。

这个解析器如何处理 MySQL 的 JSON 字段?如何将 JSON 字段解析成字符串?

对于 JSON 列,解析器只获取二进制数据并将其存储在 ColumnValue::Json(Vec) 对象中。同时提供了一个默认解析器 JsonBinary,可以将其解析为字符串。示例代码中通过 JsonBinary::parse_as_string(&bytes) 将 JSON 二进制数据转换为字符串。

如何运行 mysql-binlog-connector-rust 的测试用例?

首先使用 Docker 启动 MySQL(例如 5.7 或 8.0),开启 binlog 并配置相关参数(如 binlog_format=ROW)。然后更新 tests/.env 中的配置(如 db_url、server_id 等)。最后运行命令:cargo test --package mysql-binlog-connector-rust --test integration_test。每个测试用例会执行 SQL 生成 binlog,获取并解析 binlog,并等待 binlog_parse_millis 以将所有 binlog 解析完毕;对于大事务,可能需要增大 binlog_parse_millis。

对于 CHAR/VARCHAR 和 UNSIGNED 数字列,解析器有什么限制?用户需要注意什么?

对于 CHAR/VARCHAR 列,由于 binlog 不包含字符集信息,解析器只获取二进制数据并存储在 ColumnValue::String(Vec) 对象中,用户需根据列的元数据进行转换。对于 UNSIGNED 数字列,由于 binlog 不包含符号标志,解析器只将其解析为有符号数字,用户需根据列的元数据进行转换。

🏷️

标签

➡️

继续阅读