中间节点必须开启log_slave_updates,否则级联复制中断;需在配置文件中设置log_slave_updates=ON、log_bin、唯一server_id并重启实例,且binlog_format须与上游一致。

中间节点必须开启 log_slave_updates
这是级联复制能跑通的硬性前提。如果 mysqlB(中间节点)没开这个参数,它从 mysqlA 同步来的所有变更都不会写入自己的 binlog,下游 mysqlC 就完全收不到任何数据——SHOW SLAVE STATUS 里 Seconds_Behind_Master 会卡在 0,但 mysqlC 的 IO_Running 可能是 Yes,SQL_Running 却始终是 No,因为 relay log 里压根没东西可执行。
检查方式:SHOW VARIABLES LIKE 'log_slave_updates';,结果必须是 ON。如果为 OFF,不能只用 SET GLOBAL 临时生效(重启即丢),必须改配置文件:
log_slave_updates = ON log_bin = mysql-bin server_id = 2
改完必须重启 MySQL 实例,否则不生效。
server_id 必须全局唯一且不可复用
级联链路上每个节点的 server_id 是复制定位的唯一标识,不是“随便设个数字就行”。一旦重复,比如 mysqlB 和 mysqlC 都设成 2,主库 mysqlA 在 binlog 里记录事件时会跳过发给同 server_id 的从库,导致同步中断;更糟的是,mysqlC 可能误认 mysqlB 的 relay log 事件为自己产生的,引发 GTID 冲突或位点错乱。
实操建议:
-
mysqlA设为1,mysqlB设为2,mysqlC设为3,往后递增即可 - 避免用 IP 地址哈希、时间戳等动态值生成
server_id,容易冲突 - 上线前用
SELECT @@server_id;确认每台实例当前值
中间节点的 read_only 设置要分场景
read_only = 1 对中间节点不是强制要求,但强烈建议开启——除非你明确需要在 mysqlB 上手动写入(比如补数、DDL 操作)。开了之后,普通用户无法执行 INSERT/UPDATE/DELETE,能防误操作,也能避免因中间节点写入导致下游数据异常。
但要注意两个细节:
-
read_only不影响复制线程自身写入,SQL 线程仍可正常回放 relay log - 如果用了 GTID 复制,且后续可能做故障切换(把
mysqlB提升为主),建议同时加super_read_only = 1,防止超级用户绕过read_only - 若中间节点承担部分读流量,开启
read_only不影响查询,只禁写
中间节点的 binlog 格式必须与上游一致
复制链路中任意一环的 binlog_format 不一致,都可能导致下游解析失败或数据不一致。比如 mysqlA 是 ROW,mysqlB 改成 STATEMENT,那么 mysqlB 自己产生的 binlog 事件(比如函数调用、触发器)在 mysqlC 回放时就可能出错。
验证和统一方法:
- 在每台节点上执行
SELECT @@binlog_format; - 生产环境统一设为
ROW或MIXED,避免混用 - 修改需写入配置文件并重启,
SET GLOBAL仅临时有效 - 特别注意:MySQL 5.7+ 默认是
STATEMENT,不是ROW,别凭印象判断
级联复制最易被忽略的其实是延迟叠加——mysqlC 的延迟 = mysqlB 相对 mysqlA 的延迟 + mysqlC 相对 mysqlB 的延迟。监控时不能只看单跳,得逐级查 Seconds_Behind_Master,否则问题定位永远慢半拍。


















