go 中捕获 mysql 行级变更需依赖 go-mysql 解析 row 格式 binlog,配置 binlog_format=row、log_slave_updates=on 专用从库,持久化位点并按表+主键哈希保序,结合幂等写入避免重复丢失。

Go 里怎么捕获数据库行级变更(比如 MySQL binlog)
Go 本身不内置 CDC(Change Data Capture)能力,必须依赖外部机制或库。最常用的是解析 MySQL 的 binlog,因为它是官方支持的、低侵入、高可靠的数据变更源。别指望用定时轮询 SELECT ... WHERE updated_at > ?——延迟高、漏变更、压数据库。
实操建议:
- 用
github.com/go-mysql-org/go-mysql(原 go-mysql,维护活跃)监听 binlog:它能连接 MySQL 主库或从库,订阅指定库表,把INSERT/UPDATE/DELETE解析为结构化事件 - 务必配置 MySQL 开启
binlog_format = ROW和binlog_row_image = FULL,否则 UPDATE 可能只带主键,拿不到旧值或新值 - 避免直接消费主库 binlog;优先挂一个专用从库(
log_slave_updates=ON),防止同步逻辑拖慢主库 - 注意位点(
BinlogPos)管理:出错重启时得从上次成功提交的位置继续,推荐用外部存储(如 Etcd 或 MySQL 自身表)持久化filename+position
如何在 Go 中安全地做增量同步(避免重复/丢失)
“增量同步”不是简单地把变更写进目标库,核心难点是「至少一次」投递下的幂等性与顺序保障。MySQL binlog 天然有序,但 Go 消费端一旦并发处理、网络重试、崩溃恢复,顺序就容易乱。
实操建议:
- 按表+主键哈希分片:对每条变更事件计算
hash(table_name + primary_key),路由到固定 worker goroutine,保证单表单行的变更绝对有序 - 目标端写入前加幂等判断:例如在目标表加
event_id字段(来自 binlog 的gtid或自构唯一 ID),INSERT ... ON DUPLICATE KEY UPDATE或先SELECT再决定动作 - 不要在内存里攒批量更新后统一提交——binlog 事件之间有严格时序依赖(如先删后插),攒批会打破因果关系
- 如果目标是 Elasticsearch 或 Kafka,用
version或timestamp字段做乐观更新,避免覆盖新数据
有没有轻量替代方案?比如不碰 binlog
有,但适用场景有限。如果你无法开启 binlog、没权限配从库,或只是同步少量业务表,可以考虑基于时间戳或版本号的轮询拉取,但必须接受折损:
- 用
updated_at时间戳:每次记录上一次最大时间,下次查WHERE updated_at > ? ORDER BY updated_at, id;隐患是 DB 时钟漂移、事务提交时间晚于逻辑修改时间、同一毫秒多条变更导致漏读 - 用自增
version或seq字段:比时间戳可靠,但要求所有写入口严格递增更新该字段,业务侵入性强 - PostgreSQL 用户可直接用
logical replication+pglogrepl库,比 MySQL binlog 更易用,协议层就支持解析为 INSERT/UPDATE/DELETE 结构体 - 千万别用
SELECT * FROM t WHERE id > ?—— 软删除、归档、ID 不连续都会导致漏数据
常见 panic 和日志里藏的坑
实际跑起来最容易栽在几个不起眼的地方:
-
panic: invalid connection:go-mysql 默认复用连接,但 MySQLwait_timeout断连后不会自动重连,得自己 wrapSyncer加心跳或设SetConnMaxLifetime - 日志里反复出现
skip event type: XXX:说明你订阅了ROTATE_EVENT或FORMAT_DESCRIPTION_EVENT这类元事件,它们不含业务数据,需在OnEvent回调里显式跳过 - 同步延迟突然飙升:大概率是某条大事务(如
UPDATE t SET x=? WHERE y=?影响百万行)生成了海量 binlog 事件,go-mysql 默认单 goroutine 解析,卡住了后续事件;需提前识别大事务并拆分,或改用goyang21/go-mysql的并行解析分支(谨慎评估一致性) - 目标库写入失败后,别只打日志就丢弃事件——至少要把事件 dump 到本地文件或死信队列,否则变更永远丢失
真正难的从来不是“怎么拿到变更”,而是“怎么确保每一条都精准、不重、不丢、不错序地落地”。binlog 解析只是起点,位点管理、错误隔离、幂等设计、监控告警,缺一不可。











