主从复制仅同步数据,不自动实现读写分离;读写分离需应用或中间件显式路由,且从库须设read_only=on并配合super_read_only=1防误写。

主从复制本身不自动实现读写分离,它只负责数据同步;读写分离必须由应用层或中间件(如 MyCat、ShardingSphere、ProxySQL)显式路由 SQL——这是最容易被误解的第一步。
主库配置必须启用 binlog 且设置唯一 server-id
MySQL 启动时若未启用 binlog 或 server-id 冲突,CHANGE MASTER TO 会直接报错 ERROR 1236 (HY000)。关键项不是“开不开”,而是“开得对不对”:
-
log_bin必须是绝对路径(如/var/log/mysql/mysql-bin),不能只写mysql-bin(某些版本会静默失败) -
server-id必须是整数且全局唯一,主从不能相同;Docker 容器中常因配置挂载覆盖导致重复 -
binlog_format推荐设为ROW:避免NOW()、UUID()等函数在从库执行结果不一致 - 加
sync_binlog = 1可降低主库宕机时 binlog 丢失风险(牺牲一点写性能)
从库启动复制前必须严格校验 MASTER_LOG_FILE 和 MASTER_LOG_POS
这两个值来自 SHOW MASTER STATUS,但很多人忽略一个事实:它们只在主库当前时刻有效。如果主库在你执行 CHANGE MASTER TO 前又写了新事务,从库就会跳过部分日志,造成数据不一致。
- 正确做法:在主库执行
FLUSH TABLES WITH READ LOCK→SHOW MASTER STATUS→ 记录File和Position→UNLOCK TABLES - 如果主库无法锁表(如生产环境),可用
mysqldump --master-data=2导出并解析 dump 文件头里的 binlog 位置 - 从库执行
START SLAVE后,必须立刻查SHOW SLAVE STATUS\G,确认Slave_IO_Running: Yes且Slave_SQL_Running: Yes,任一为No都要查Last_IO_Error或Last_SQL_Error
read_only=1 不等于“完全只读”,super 用户仍可写
从库设了 read_only = 1,但 root 或任何 SUPER 权限用户依然能执行写操作——这会导致主从数据 divergence,且 SQL Thread 重放时可能报错中断。
- 真正安全的做法是:用普通账号连接从库,并确保该账号没有
SUPER权限 - 配合
super_read_only = 1(MySQL 5.7+)可禁用所有用户的写权限,包括 super - 若用 MyCat 或 ShardingSphere 做读写分离,务必在中间件里配置
writeHost和readHost分开,否则应用直连从库仍可能误发写语句
最常被跳过的一步是验证延迟:即使 SHOW SLAVE STATUS 显示正常,Seconds_Behind_Master 也可能持续增长。尤其在从库负载高、大事务回放慢、或网络抖动时,读请求若发到延迟几秒的从库,业务上就可能出现“刚提交查不到”的问题——这不是配置错误,而是架构必须面对的真实约束。











