MySQL Replay(非 GTID)

非 GTID 情况

1 切换前置检查

1.1 设置只读

执行 "SET GLOBAL READ_ONLY=1";

1.2 检查是否本地回放完成

slave_status.master_log_file == slave_status.relay_master_log_file

同时

slave_status.read_master_log_pos == slave_status.exec_master_log_pos

1.3 停止 slave io_thread

执行 "STOP SLAVE IO_THREAD";

4.4 授权 Grant replication privileges for slaves

4.5 返回切换辅助信息

[relay log 中的心跳值必须 >= 心跳表中的 value] or [binlog 中的心跳值必须 = 心跳表中 value]

4.5.1 检查逻辑

(1)日志类型判断

  • 如果 binlog 和 relay log 都不存在,直接返回失败(NO_LOGS_FIND)。

  • 如果 只有 relay log,优先从 relay log 查找。

  • 如果 只有 binlog,优先从 binlog 查找。

  • 如果 两者都存在,进入复杂逻辑(需结合心跳值和节点历史角色判断)。

(2) 心跳值校验(NOT_SURE 分支)

  • 调用 MySQLMgr::GetHeartbeatValue 获取心跳表中的最新进度值(value)。

  • 根据 has_master_before 决定 优先检查 binlog 还是 relay log

    • 曾是主库:先查 binlog(要求 checkpoint 必须与心跳值一致),再查 relay log。

    • 曾是从库:先查 relay log(要求 checkpoint ≥ 心跳值),再查 binlog。

  • 如果两者均未找到匹配的 checkpoint,返回失败。

(3) 结果返回

  • 通过 use_binlog 返回实际使用的日志类型。

  • 返回 0(成功)或 -1(失败)。

4.5.2 binlog 和 relay log 格式

  • 主从复制

    • 从库的 relay-log.info 文件记录:

    • 表示从库已应用到 relay-log.000001 的 1234 位置,对应主库的 binlog.000005 的 5678 位置。

  • GTID 模式(全局事务标识符):

    • 使用 gtid_executed 变量记录已应用的事务 ID 集合,替代文件 + position。

2 提升新主

3 常见问题

3.1 主库故障导致的不完整事务

如果主库在提交事务后、传输binlog给从库的过程中崩溃,从库只接收到部分事务的binlog事件。

此时,Read_Master_Log_Pos 记录已接收到的位置,而Exec_Master_Log_Pos停留在上一个完整事务的结束位置。则 Read_Master_Log_Pos ≠ Exec_Master_Log_Pos , 认为本地回放没有成功

此时 stop slave 会卡 60s。

如果中继日志中的最后一个事务只被接收到一半,并且多线程副本协调器已经开始将事务调度给一个工作人员,那么 STOP SLAVE最多等待 60 秒以接收事务。

如果发现本地回放没有完成,自动拉起 slave,将陷入死循环中。

3.2 本地回放一直未完成

grep -E "2025|Master_Log_File|Relay_Master_Log_File|Read_Master_Log_Pos|Exec_Master_Log_Pos" slave_status.20251014

Last updated