MySQL主从同步中断时binlog被清理会导致不可逆数据丢失,因从库未拉取的binlog被purge;生产环境应设expire_logs_days≥7、监控磁盘并禁用自动清理,改用校验后手动PURGE。

MySQL主从同步中断时binlog被清理导致数据丢失
主从复制断开后,如果 expire_logs_days 设置过小或磁盘空间不足触发自动 purge,从库还没来得及拉取的 binlog 就会被删掉,造成不可逆的数据断裂。这不是“同步慢”,是根本没机会同步。
- 检查当前 binlog 保留策略:
SHOW VARIABLES LIKE 'expire_logs_days';,默认是 0(永不过期),但很多运维脚本会强制设为 1–7 - 生产环境建议设为至少 7 天,并配合磁盘监控:如果
df -h /var/lib/mysql使用率超 85%,MySQL 可能主动 purge 最老 binlog 来保活 - 更稳妥的做法是关闭自动清理,改用定时脚本 + 校验逻辑:先
SHOW BINARY LOGS;确认最老 binlog 被从库读取完毕,再手动PURGE BINARY LOGS TO 'mysql-bin.000123';
mysqldump 导出时未加 --single-transaction 导致一致性破坏
不加这个参数时,mysqldump 对非事务表(如 MyISAM)会锁表,对 InnoDB 表则可能在导出过程中写入新数据,最终 dump 文件里出现部分旧、部分新记录,恢复后状态错乱。
- 必须加上
--single-transaction(仅对 InnoDB 有效),它利用 MVCC 在事务快照中读取,全程不锁表 - 但要注意:该参数和
--lock-tables冲突,后者是默认行为,所以务必显式禁用:--single-transaction --skip-lock-tables - 如果库中混有 MyISAM 表,
--single-transaction无效,必须停写或改用xtrabackup
GTID 模式下 CHANGE MASTER TO 指定错误 exec_gtid_set 引发跳过事务
手动切换主从或搭建新从库时,用 CHANGE MASTER TO MASTER_AUTO_POSITION = 0 后指定 MASTER_LOG_FILE 和 MASTER_LOG_POS,若位置点落在某个 GTID 事务中间,MySQL 会直接跳过整个 GTID,导致那条事务彻底丢失——不是延迟,是永久消失。
- 优先使用
MASTER_AUTO_POSITION = 1,由 MySQL 自动匹配已执行过的 GTID 集合 - 若必须指定位点,先在原主库查:
SELECT BINLOG_GTID_POS('mysql-bin.000123', 123456);,拿到对应 GTID,再用SET GTID_NEXT='xxx'; BEGIN; COMMIT;手动注入校准 - 迁移前务必确认从库
gtid_executed包含所有应有 GTID:SELECT * FROM performance_schema.replication_applier_status_by_coordinator;
从库设置 relay_log_purge=OFF 后磁盘爆满引发复制停止
为防 relay log 被误删而关掉自动清理,看似安全,实则埋雷:relay log 不释放,磁盘撑满后 SQL thread 直接 halt,错误日志里只报 OS error code 28: No space left on device,没人意识到是 relay log 占满。
- 不要长期关闭
relay_log_purge,它是安全的——只有当 SQL thread 执行完某段 relay log 后才会删,不会删正在用的 - 真正要控的是
relay_log_space_limit,设一个硬上限(如 10G),超限后 IO thread 暂停写入,避免雪崩 - 定期清理残留:
PURGE RELAY LOGS BEFORE '2024-05-01 00:00:00';,注意该命令需在从库 STOP SLAVE 后执行,否则报错
真正危险的不是配置项本身,而是多个“看起来合理”的设置叠加:比如 binlog 过期短 + relay log 不清理 + 从库延迟高。等发现丢数据,binlog 和 relay log 都没了,连溯源都做不到。










