延迟复制需人工干预且配置严格:必须先STOP SLAVE SQL_THREAD再设MASTER_DELAY,监控看SQL_Remaining_Delay而非Seconds_Behind_Master,GTID模式禁用sql_slave_skip_counter,务必启用read_only和super_read_only。

MASTER_DELAY,会直接报错 ERROR 3085,整个延迟机制就失效了。
STOP SLAVE SQL_THREAD 必须先执行,否则 CHANGE MASTER TO 失败
MySQL 要求必须先暂停 SQL 线程,才能设置延迟。直接运行 CHANGE MASTER TO MASTER_DELAY = 3600 会触发错误:ERROR 3085 (HY000): This operation cannot be performed with a running slave sql thread。这不是警告,是硬性拒绝。
- 只停 SQL 线程(保留 IO 线程继续接收 binlog):
STOP SLAVE SQL_THREAD; - 再设延迟:
CHANGE MASTER TO MASTER_DELAY = 3600; - 最后重启 SQL 线程:
START SLAVE SQL_THREAD; - 如果从库已同步一段时间,
CHANGE MASTER TO会清空当前位点(Relay_Master_Log_File和Exec_Master_Log_Pos),务必提前用SHOW SLAVE STATUS\G记下Master_Log_File和Read_Master_Log_Pos,并在CHANGE MASTER TO中显式补全,否则可能从 binlog 开头重放
监控必须看 SQL_Remaining_Delay,不是 Seconds_Behind_Master
Seconds_Behind_Master 是总滞后秒数,不等于你设的延迟值,更不能反映“是否还在延迟等待中”。真正决定你有没有抢救窗口的字段是 SQL_Remaining_Delay —— 它是倒计时,只有 SQL 线程卡在延迟队列里时才非 NULL。
- 大事务正在执行(如长 UPDATE),
Seconds_Behind_Master飙到 10000+,但SQL_Remaining_Delay仍是 3600 → 正常,延迟仍在生效 -
Seconds_Behind_Master = 0,但SQL_Remaining_Delay = 3590→ 实际仍在延迟中,只是没积压其他事件 - 监控脚本若只查
Seconds_Behind_Master,会误判延迟已失效,错过抢救时机
GTID 模式下不能用 sql_slave_skip_counter 跳过误删语句
如果你启用了 gtid_mode = ON(生产环境强烈推荐),SET GLOBAL sql_slave_skip_counter = 1 会破坏 GTID 集合一致性,导致复制中断甚至数据错乱,绝对禁用。
- 误删发生后,正确做法是:立刻在延迟从库上执行
STOP SLAVE SQL_THREAD;,然后用mysqlbinlog解析中继日志,定位到误删前最后一个事务位置 - 再用
START SLAVE UNTIL SQL_AFTER_GTIDS = 'xxx:yyy'精确回放到那个 GTID - 导出数据后恢复主库,整个过程不碰
sql_slave_skip_counter
read_only 和 super_read_only 必须启用,否则延迟从库反而成风险点
延迟从库本身是可写的,如果不加防护,运维或应用误连上去执行 DML,会导致从库数据污染,失去“干净备份”价值。
- 在从库配置文件中设置:
read_only = ON(普通用户无法写) - 同时设置:
super_read_only = ON(连 root 也无法写,除非先关掉它) - 这两项必须在延迟配置完成后立即启用,且需确认未被运行时动态关闭过(检查
SELECT @@read_only, @@super_read_only;) - 别指望靠权限控制代替这两个参数——只要账号有 SUPER 权限,就能绕过
read_only;只有super_read_only才能真正锁死
SQL_Remaining_Delay 的值班人,或者一次忘记开 super_read_only 的初始化操作,就足以让整套防御形同虚设。

















