mysql增量同步需确保binlog开启且配置合规:server_id为非0唯一整数,binlog_format设为row,binlog_row_image=full;起始位点应通过flush tables with read lock+show master status获取或使用gtid;解析需用--base64-output=decode-rows -v参数或专业库;追平时采用幂等写入避免冲突。

Binlog 开启没?先确认 server_id 和格式
MySQL 增量同步的前提不是“有没有 Binlog”,而是它是否真正启用且配置合规。常见现象是执行 SHOW VARIABLES LIKE 'log_bin'; 返回 ON,但依然无法被下游消费——大概率是 server_id 未设或为 0,或者 binlog_format 是 STATEMENT(不推荐用于同步)。
-
server_id必须是非 0 整数,且在整个复制拓扑中唯一;主从混用相同值会导致连接拒绝或数据错乱 -
binlog_format推荐设为ROW:能精确捕获行级变更,避免函数、临时表、非确定性语句引发的主从不一致 - 修改后需重启 MySQL 或动态生效(
SET GLOBAL binlog_format = 'ROW';),但注意:已有事务不会回滚重写,只影响后续日志 - 检查是否开启
binlog_row_image = FULL(默认值),否则UPDATE可能只记录变更列,下游解析失败
怎么安全地获取起始位点?别直接用 SHOW MASTER STATUS
迁移开始前必须锁定一个确定的、可复现的 Binlog 位置,否则追平过程会漏数据或重复。直接执行 SHOW MASTER STATUS; 拿到的位置,是当前最新写入点,不代表所有业务事务已落盘——尤其在高并发写入时,极易丢掉正在提交中的事务。
- 用
FLUSH BINARY LOGS;切换新日志文件,再立刻执行SHOW MASTER STATUS;,可降低位点漂移风险 - 更稳妥的方式是配合全局读锁:
FLUSH TABLES WITH READ LOCK;→SHOW MASTER STATUS;→ 记录File和Position→UNLOCK TABLES;(注意锁期间写入阻塞) - 若业务不可停写,改用
mysqlbinlog --read-from-remote-server+ GTID 模式:先查SELECT @@global.gtid_executed;,下游从该 GTID 集合开始拉取,语义更可靠
解析 Binlog 时,为什么 mysqlbinlog 工具输出看不懂?
mysqlbinlog 默认输出的是原始事件二进制转义内容,不是 SQL。直接看 UPDATE 事件会看到一堆 @1=... @2=... 字段引用,这是 ROW 格式下的字段序号映射,和表结构强绑定——一旦中途加减列、改类型,解析就失效。
- 加
--base64-output=DECODE-ROWS -v参数才能看到可读的伪 SQL(如### UPDATE `db`.`t1`+### WHERE+### SET) - 但这类输出仍是调试用,不能直接执行:含注释标记(
###)、无事务边界、UPDATE 不带主键条件、DELETE 缺少 WHERE 子句细节 - 生产环境别手写解析逻辑;用成熟客户端库(如 Python 的
mysql-replication、Go 的go-mysql)处理事件流,它们自动维护列定义缓存、支持 GTID、能跳过特定库/表 - 注意时区:Binlog 中的时间戳按服务器
system_time_zone记录,下游解析时若未对齐,datetime字段可能偏移
追平阶段如何避免主键冲突和重复应用?
增量同步不是简单“把日志重放一遍”。当目标库已有历史数据(全量导入后),再应用 Binlog 里的 INSERT,必然主键冲突;而跳过冲突又可能掩盖真实异常。
- 全量导入时,务必禁用目标库的自增主键(
SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;),并用INSERT IGNORE或REPLACE INTO处理重复 - 增量阶段,推荐用“幂等写入”:将
INSERT转为INSERT ... ON DUPLICATE KEY UPDATE,UPDATE保留原 WHERE 条件(含主键+版本号/时间戳),DELETE加上LIMIT 1防误删 - 不要依赖
sql_log_bin=0关闭日志来跳过某些操作——这会让下游永远丢失这部分变更,且影响主从一致性判断 - 最易被忽略的一点:Binlog 里
CREATE TABLE事件不含字符集声明(如DEFAULT CHARSET=utf8mb4),若源库表用utf8mb4_0900_as_cs而目标库默认是utf8mb4_0900_ai_ci,后续比较会出错










