2. MySQL Binlog 基础:三种格式、开启配置与 mysqlbinlog 工具
聊到 CDC,Binlog 是绕不开的起点。我经常跟团队里的新人说,搞懂 Binlog,实时数据这条路你就走通了一半。说白了,Binlog 就是 MySQL 的“操作日记”,记录了所有数据变更。今天咱们就把它的格式、配置和工具讲透。
2.1 Binlog 的三种格式:STATEMENT、ROW、MIXED
Binlog 有三种记录格式。选哪种,直接影响你的 CDC 方案能不能跑得稳。我见过不少项目因为格式选错,后期踩了大坑。
2.1.1 STATEMENT 格式
这种格式只记录 SQL 语句本身。比如你执行了 UPDATE users SET age=age+1 WHERE id>100,Binlog 里就记下这条 SQL。
优点:日志量小,一条 SQL 可能影响一万行,但只记一条记录。
缺点:某些场景下数据不一致。比如用了 NOW()、UUID() 这类函数,主从重放时结果可能不同。
我记得有一次排查线上问题,发现主从数据对不上。查了半天,罪魁祸首就是 STATEMENT 格式下用了 LIMIT 子句的 UPDATE。主库和从库的数据排序不一样,更新结果就偏了。嗯,从那以后我对 STATEMENT 格式就格外小心。
2.1.2 ROW 格式
ROW 格式记录的是每一行数据的变化细节。还是刚才那个 UPDATE,它会记下每一行修改前和修改后的完整数据。
我个人强烈推荐:生产环境用 ROW 格式。CDC 场景下,ROW 格式能精确捕获每一行变更,不会丢失上下文。Debezium、Canal 这些工具都依赖 ROW 格式。
缺点也很明显——日志量大。一次批量更新 10 万行,Binlog 文件会暴涨。我曾经在一个日活千万的系统上,因为没预估好 ROW 格式的日志量,磁盘差点写爆。你想想看,那场面多刺激。
2.1.3 MIXED 格式
MIXED 是前两种的混合体。MySQL 自己判断:安全的 SQL 用 STATEMENT 记,不安全的(比如带函数、子查询的)自动切到 ROW。
听起来很智能对吧?但我在实际项目中很少用。为什么?因为不可控。你没法精确预判 MySQL 什么时候切格式,CDC 消费端处理起来很麻烦。说白了,MIXED 适合“通用场景”,不适合“CDC 专用场景”。
| 对比维度 | STATEMENT | ROW | MIXED |
|---|---|---|---|
| 日志量 | 小 | 大 | 中等 |
| 数据一致性 | 可能不一致 | 完全一致 | 基本一致 |
| CDC 适用性 | 不推荐 | 强烈推荐 | 不推荐 |
| 典型场景 | 简单主从复制 | 数据同步、审计、CDC | 通用复制 |
2.2 Binlog 的开启与配置
Binlog 默认是关闭的。你需要手动开启。我建议你在安装 MySQL 时就配好,别等到需要 CDC 了再回头改。
2.2.1 基础配置
编辑 MySQL 配置文件 my.cnf(Linux)或 my.ini(Windows),在 [mysqld] 段下添加:
[mysqld]
# 开启 Binlog
log-bin=mysql-bin
# 设置格式为 ROW
binlog-format=ROW
# 每个 Binlog 文件最大 1GB
max_binlog_size=1G
# 保留 7 天的 Binlog
expire_logs_days=7
# 要记录的数据库(可选)
binlog-do-db=your_database
# 忽略的数据库(可选)
binlog-ignore-db=mysql
我曾经踩过的坑:expire_logs_days 设得太短,导致 CDC 消费端还没读完,Binlog 就被清理了。建议根据你的消费速度,至少保留 3-7 天。如果数据量大,可以配合 binlog_expire_logs_seconds 做更精细的控制。
2.2.2 验证配置是否生效
重启 MySQL 后,执行以下命令检查:
-- 查看 Binlog 是否开启
SHOW VARIABLES LIKE 'log_bin';
-- 查看当前 Binlog 格式
SHOW VARIABLES LIKE 'binlog_format';
-- 查看所有 Binlog 文件列表
SHOW BINARY LOGS;
如果 log_bin 显示 ON,binlog_format 显示 ROW,恭喜你,配置成功了。
2.2.3 在线切换 Binlog 格式
有些场景下,你可能需要临时切换格式。比如做一次大表归档,想减少日志量。MySQL 支持在线切换:
-- 当前会话级别切换
SET SESSION binlog_format = STATEMENT;
-- 全局级别切换(需要 SUPER 权限)
SET GLOBAL binlog_format = MIXED;
但注意,全局切换后,新的连接才会生效。已经存在的连接不受影响。我一般只在排查问题时用会话级别切换,生产环境从不乱动全局配置。
2.3 mysqlbinlog 工具的使用
mysqlbinlog 是 MySQL 自带的 Binlog 解析工具。虽然现在很多 CDC 框架都封装了解析逻辑,但掌握这个工具,能帮你快速定位问题。
2.3.1 基本用法
查看 Binlog 文件内容:
# 直接查看
mysqlbinlog mysql-bin.000001
# 指定数据库
mysqlbinlog --database=your_db mysql-bin.000001
# 指定起始和结束位置
mysqlbinlog --start-position=100 --stop-position=500 mysql-bin.000001
# 指定时间范围
mysqlbinlog --start-datetime="2024-01-01 00:00:00" --stop-datetime="2024-01-02 00:00:00" mysql-bin.000001
2.3.2 解析 ROW 格式的 Binlog
ROW 格式的 Binlog 默认是二进制内容,直接看是乱码。需要加 --base64-output=DECODE-ROWS 和 -v 参数:
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001
这样就能看到类似这样的输出:
### UPDATE `your_db`.`users`
### WHERE
### @1=1001
### @2='张三'
### @3='zhangsan@example.com'
### SET
### @1=1001
### @2='张三'
### @3='newemail@example.com'
你看,每一行变更的前后数据都清清楚楚。这就是 CDC 能精确捕获数据变化的基础。
我个人的调试习惯:先用 mysqlbinlog 解析出 SQL,确认数据变更是否符合预期,再部署 CDC 任务。这能省掉很多排查时间。
2.3.3 恢复数据
mysqlbinlog 还可以用来恢复数据。比如你误删了数据,可以把 Binlog 中的操作回放:
# 将 Binlog 导出为 SQL 文件
mysqlbinlog mysql-bin.000001 > binlog.sql
# 然后执行 SQL 恢复
mysql -u root -p < binlog.sql
但要注意,直接回放整个 Binlog 会把所有操作重做一遍。更精细的做法是指定位置或时间范围,只恢复你需要的那部分。
2.4 知识体系总览
下面这张图把本章的核心知识点串起来了。你可以把它当作一个快速索引:
这张图把 Binlog 的三大块——格式、配置、工具——串在了一起。你顺着这个结构往下学,思路会清晰很多。
2.5 本章小结
Binlog 是 CDC 的基石。搞懂了这三种格式的区别,你就能选对方案;掌握了配置方法,你就能让系统稳定运行;会用 mysqlbinlog,你就能在出问题时快速定位。我个人觉得,这一章的内容值得你花时间反复消化。毕竟,地基打不牢,后面盖再高的楼也悬。