位点丢失需以从库Relay_Master_Log_File和Exec_Master_Log_Pos为准重锚定,不可盲填主库当前位点;先查SHOW SLAVE STATUS\G定位Last_IO_Error或Last_SQL_Error,再依线程状态选择用中继日志末尾pos或启用relay_log_recovery修复。

位点丢失不是“丢了一点”,而是复制链路已断裂,必须靠从库最后成功执行的位置重锚定,不能凭主库当前状态瞎填。
怎么看清到底丢在哪一步
先别动 CHANGE MASTER TO —— 执行 SHOW SLAVE STATUS\G,重点盯三个字段:
-
Last_IO_Error:如果是error connecting to master或timeout,基本就是网络断了;如果带authentication failed,大概率是主库改了密码或插件不兼容 -
Last_SQL_Error:如果为空但Slave_SQL_Running: No,说明 SQL 线程自己卡死,不是网络问题 -
Relay_Master_Log_File和Exec_Master_Log_Pos:这才是关键——它们代表从库 SQL 线程**最后成功执行的那条语句在主库 binlog 中的位置**,只要这两个值存在且非空,就还能用
怎么安全重设 MASTER_LOG_FILE 和 MASTER_LOG_POS
别抄主库 SHOW MASTER STATUS 的最新位置,那是还没发出去的,强行指定会跳过中间所有日志。
- 如果
Slave_IO_Running: Yes但Slave_SQL_Running: No:直接用Relay_Master_Log_File和Exec_Master_Log_Pos填进CHANGE MASTER TO MASTER_LOG_FILE = 'xxx', MASTER_LOG_POS = yyy - 如果 IO 和 SQL 都挂了,但 relay log 文件还在(默认在
/var/lib/mysql/relay-bin.000xxx):用mysqlbinlog --base64-output=decode-rows -v relay-bin.000xxx | tail -30查最后一条COMMIT对应的end_log_pos - 如果 relay log 已损坏(报
Relay log read failure):确认relay_log_recovery = 1已配置并重启 mysqld,它会自动放弃损坏中继日志、重建连接
为什么 START SLAVE 后立刻又报错
重设位置只是“续上”,不代表问题根除。常见真因:
- 主从表结构不一致:比如从库少了个索引、字段默认值不同、
ENGINE不一样,SHOW CREATE TABLE对一遍 - 从库残留临时表:
SHOW TABLES LIKE 'tmp_%',有就删掉 - 主库
binlog_format = STATEMENT却执行了NOW()、UUID()、LOAD_FILE()这类非确定性函数:切到ROW或MIXED更稳妥 - GTID 模式下混用
MASTER_LOG_FILE:启用了MASTER_AUTO_POSITION = 1就绝对不要手动指定位置,该用SET GLOBAL gtid_slave_pos = 'xxx'
修复后怎么确认真追平了
Seconds_Behind_Master: 0 不等于数据一致——它只表示“没积压”,不代表“内容相同”。
- 等
Slave_IO_Running: Yes且Slave_SQL_Running: Yes稳定 2 分钟以上再查 - 对比主从的
Master_Log_File / Read_Master_Log_Pos(IO 线程拉到哪)和Relay_Master_Log_File / Exec_Master_Log_Pos(SQL 线程执行到哪),两组值必须完全一致 - 抽样校验:选几个高频更新表,用
SELECT COUNT(*), MD5(GROUP_CONCAT(...))算哈希比对(注意排序和 NULL 处理)
网络波动本身不破坏数据,但重连策略和位点选取稍有偏差,就会让从库跳过一段逻辑、或重复执行某条语句——真正难的从来不是“怎么续”,而是“续完之后,还敢不敢信”。


















