1236错误不是数据损坏,而是从库持过期“入场券”向主库索要日志时被拒——主库在binary log index中查无此文件或位点越界;修复必须严格区分gtid与file/pos模式,误用reset master或sql_slave_skip_counter将导致重复执行或同步断裂。

直接说结论:1236 错误不是数据损坏,而是从库拿着一张过期的“入场券”去主库要日志,主库查了索引文件发现这号票根本没发过——要么文件被删了,要么位点写错了,要么 GTID 对不上。修复动作必须匹配当前复制模式(GTID 还是 file/pos),乱用 RESET MASTER 或 sql_slave_skip_counter 会引发重复执行或同步断裂。
确认错误类型:区分 'Could not find first log file' 和 'position > file size'
先看 Last_IO_Error 具体内容,它决定你该走哪条路:
-
'Could not find first log file name in binary log index file':主库上压根没有从库要的那个 binlog 文件(比如从库记着要读mysql-bin.000127,但主库SHOW BINARY LOGS里最小的是mysql-bin.000135) -
'Client requested master to start replication from position > file size':文件还在,但从库请求的位置超出了该 binlog 实际长度(常见于主库异常重启后 binlog 写入错位)
前者大概率需重设起点或重建从库;后者通常只需跳到下一个 binlog 起始位置 pos=4 即可恢复。
非 GTID 模式下重设复制起点
适用于 binlog_format=STATEMENT 或未启用 GTID 的传统复制。核心是让从库从主库现存最早的 binlog 开始拉取:
- 登录主库,执行
SHOW BINARY LOGS,记下第一个文件名(如mysql-bin.000291) - 从库执行:
STOP SLAVE;→CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000291', MASTER_LOG_POS=4;→START SLAVE; - 注意:
MASTER_LOG_POS必须设为4,这是每个 binlog 文件合法起始位置,设成0或其他值会再次触发 1236 - 如果改完仍报错,说明主库连
mysql-bin.000291都已删除,此时无法在线修复,必须走备份恢复流程
GTID 模式下安全设置 gtid_purged
GTID 模式下不能碰 RESET MASTER,也不能用 sql_slave_skip_counter。关键在于让从库的 gtid_purged 包含主库已清理掉的那部分 GTID:
- 先在从库执行
STOP SLAVE;,再查本机已执行的 GTID:SELECT @@global.gtid_executed; - 登录主库,查其已清理的 GTID:
SELECT @@global.gtid_purged; - 把主库的
gtid_purged和从库gtid_executed中属于主库 UUID 的部分合并(去重),例如:aaa-bbb:1-100,ccc-ddd:1-50 - 在从库执行:
SET GLOBAL gtid_purged = '合并后的字符串';(注意:必须在gtid_executed为空时才能设,否则先RESET MASTER——但此举会清空本机所有 GTID 记录,仅限测试环境慎用) - 最后
START SLAVE;,检查Retrieved_Gtid_Set是否开始增长
漏掉从库自己已执行的 GTID,会导致事务重复应用;多写了不属于主库的 GTID,会让从库跳过本该执行的事务——这个字符串必须精确。
什么时候必须重建从库?
当主库 SHOW BINARY LOGS 返回的最早文件,比从库 SHOW SLAVE STATUS\G 中的 Master_Log_File 更新,且你确认中间缺失的 binlog 没有备份、也没法从其他从库补全时,就到了重建节点。这不是失败,而是设计闭环的一部分:延迟超过 expire_logs_days 的从库,本就不该继续参与线上服务。此时最稳的路径是:mysqldump --master-data=2 --single-transaction 做一致性快照,导入后用 dump 文件里的 CHANGE MASTER TO 行重置,而不是靠猜位点硬顶。











