master_delay需先停sql线程再配置,监控应盯sql_remaining_delay而非seconds_behind_master,gtid模式禁用sql_slave_skip_counter,且change master to会清空位点须显式补全。

MASTER_DELAY 配置本身不能自动防误删,它只提供一个可控的抢救时间窗口——前提是操作正确、监控到位、响应及时。错一步,比如没停 SQL 线程就改参数,整个机制就直接失效。
STOP SLAVE SQL_THREAD 必须先执行,否则 CHANGE MASTER TO MASTER_DELAY 报错
MySQL 强制要求:修改 MASTER_DELAY 前,SQL 线程必须处于停止状态。IO 线程可以继续运行(保持接收 binlog),但 SQL 线程必须停。
常见错误现象:ERROR 3085 (HY000): This operation cannot be performed with a running slave sql thread
正确顺序只能是:
STOP SLAVE SQL_THREAD;CHANGE MASTER TO MASTER_DELAY = 3600;START SLAVE SQL_THREAD;
如果用 STOP SLAVE; 全停,也能过,但会中断 IO 接收,导致 relay log 断流;只停 SQL 线程才是标准做法。
监控必须盯 SQL_Remaining_Delay,不是 Seconds_Behind_Master
Seconds_Behind_Master 是总延迟秒数,受大事务、从库性能拖累,会剧烈波动,不能反映“是否还在延迟等待中”。
真正决定你有没有抢救机会的字段是 SQL_Remaining_Delay —— 它是倒计时,只有 SQL 线程卡在延迟队列里时才非 NULL。
典型误判场景:
- 大事务正在执行 →
Seconds_Behind_Master = 12000,但SQL_Remaining_Delay = 3600→ 延迟仍在生效 - 无积压、刚执行完一个事务 →
Seconds_Behind_Master = 0,但SQL_Remaining_Delay = 3590→ 实际仍卡在延迟中
监控脚本若只查 Seconds_Behind_Master,会漏掉真实延迟状态,错过关键抢救时机。
GTID 模式下禁用 sql_slave_skip_counter,误删后必须用 GTID 定位回放
启用了 gtid_mode = ON 的环境,SET GLOBAL sql_slave_skip_counter = 1 会破坏 GTID 集合一致性,导致复制断裂甚至数据错乱,绝对不可用。
误删发生后的标准动作是:
- 立刻执行
STOP SLAVE SQL_THREAD; - 用
mysqlbinlog解析中继日志,定位到误删前最后一个完整事务的 GTID - 执行
START SLAVE UNTIL SQL_AFTER_GTIDS = 'xxx:yyy'精确回放到该位置
整个过程不碰 sql_slave_skip_counter,也不依赖位点(Relay_Master_Log_File/Exec_Master_Log_Pos),纯 GTID 驱动。
配置 MASTER_DELAY 会清空原有复制位点,必须显式补全 MASTER_LOG_FILE 和 MASTER_LOG_POS
CHANGE MASTER TO 是重置操作,无论是否指定 MASTER_DELAY,只要执行了,就会清空当前 Relay_Master_Log_File 和 Exec_Master_Log_Pos。
后果很严重:如果不补全主库当前 binlog 位置,从库可能从 binlog 开头重放,造成重复写入或主键冲突。
安全做法是:
- 执行前先记下:
SHOW SLAVE STATUS\G中的Master_Log_File和Read_Master_Log_Pos - 在
CHANGE MASTER TO中显式带上:MASTER_LOG_FILE = 'xxx',MASTER_LOG_POS = yyy - 即使只改延迟,也建议把所有连接参数(
MASTER_HOST,MASTER_USER,MASTER_PASSWORD,MASTER_PORT)一并带全,避免隐式覆盖
这步容易被跳过,但一旦出错,恢复成本远高于多敲几行命令。











