mysql 8.0导出增量binlog需先确认log_bin=on且binlog_format为row或mixed;再通过mysqlbinlog按事务边界定位文件与position,配合--base64-output=decode-rows -v导出,并根据gtid状态选择--skip-gtids或确保目标库gtid一致。

确认MySQL 8.0是否启用binlog及格式
导出增量binlog的前提是MySQL已开启二进制日志,且格式支持基于行(ROW)或混合模式(MIXED)。语句级(STATEMENT)在部分场景下可能无法精确还原变更,尤其涉及函数、临时表等。
执行以下命令验证:
SHOW VARIABLES LIKE 'log_bin';
返回 ON 才能继续。再查格式:
SHOW VARIABLES LIKE 'binlog_format';
若为 STATEMENT,建议先评估业务兼容性再切换——某些DDL或非确定性函数会导致主从不一致。
-
log_bin必须为ON,否则无binlog可导 -
binlog_row_image建议设为FULL(默认值),避免UPDATE/DELETE时缺失旧值 - 确保
expire_logs_days或binlog_expire_logs_seconds足够大,目标时间段的binlog未被自动清理
定位指定时间段对应的binlog文件和位置
MySQL不支持直接按时间范围导出binlog,必须先查出该时间段起止对应的binlog文件名和偏移量(position)。核心工具是 mysqlbinlog 的 --base64-output=DECODE-ROWS -v 配合时间过滤。
先列出当前所有binlog:
mysql -u root -p -e "SHOW BINARY LOGS;"
再用 mysqlbinlog 查看最早可能包含目标时间的文件头(含时间戳):
mysqlbinlog --no-defaults --base64-output=DECODE-ROWS -v /var/lib/mysql/binlog.000012 | head -20
找到 # at 4 后紧邻的 #240520 10:23:45 server id 1 end_log_pos 123 这类行,即事件时间戳。
- 不要依赖
mysqlbinlog --start-datetime直接导出——它只按event header时间粗略截断,可能漏掉跨文件的事务 - 事务是原子单位:一个事务可能横跨多个binlog文件,
--start-datetime和--stop-datetime仅对单个文件生效,无法保证事务完整性 - 更可靠的做法:用
mysqlbinlog --base64-output=DECODE-ROWS -v扫描各文件,人工或脚本提取第一个 >= 起始时间的end_log_pos,以及最后一个 end_log_pos
使用 mysqlbinlog 按 position 精确导出增量日志
拿到起始文件+position 和结束文件+position 后,分两步导出:
① 若起止在同一文件(如 binlog.000012),直接用 --start-position 和 --stop-position:
mysqlbinlog --no-defaults --base64-output=DECODE-ROWS -v \ --start-position=123 --stop-position=4567 \ /var/lib/mysql/binlog.000012 > incremental.sql
② 若跨文件(如从 binlog.000012 末尾到 binlog.000013 中间),需分别导出并手动拼接,注意保留 BEGIN/COMMIT 完整性:
- 对起始文件:用
--start-position导出到文件末尾(不加--stop-position) - 对中间文件:全量导出(不加任何position参数)
- 对结束文件:用
--stop-position截断,且必须确保该position落在完整事务内(不能切在COMMIT之后、下一个BEGIN之前) - 导出时务必加
--base64-output=DECODE-ROWS -v,否则ROW格式事件不可读,也无法被mysql正确重放
导入前必须验证事务边界与GTID一致性
导出的 incremental.sql 不是普通SQL,而是带 SET @@SESSION.GTID_NEXT 和 BINLOG ' 的特殊格式。直接 mysql 可能失败,尤其在启用了 <code>gtid_mode=ON 的实例上。
检查导出内容是否含GTID:
grep -E 'GTID_NEXT|BINLOG' incremental.sql | head -5
若存在 SET @@SESSION.GTID_NEXT,则目标库必须也开启GTID,且 enforce_gtid_consistency=ON;否则需先在导出时加 --skip-gtids 参数(会丢弃GTID信息,靠position回放)。
- 用
--skip-gtids导出后,导入时不会校验GTID冲突,但要求目标库的binlog position可衔接(通常需先STOP SLAVE,再CHANGE MASTER TO ... MASTER_LOG_FILE='x', MASTER_LOG_POS=y) - 若导出含
BINLOG '行,说明是row格式编码,必须用mysqlbinlog解析后重放,不能用普通mysql客户端执行——会报错ERROR 1235 (42000) - 最稳妥的回放方式:用
mysqlbinlog输出管道给mysql,例如:mysqlbinlog --no-defaults --skip-gtids /tmp/inc.sql | mysql -u root -p
时间范围导出真正的难点不在命令本身,而在于事务边界的识别和GTID上下文的保持——跳过任意一个 COMMIT 或混用不同GTID mode的实例,都会导致数据不一致。











