主库负责写入和生成binlog日志,从库通过io线程拉取并写入relay-log、sql线程串行重放实现同步;角色不可互换但可手动切换,读写分离中间件依赖底层主从复制保障一致性。

主库(Master)只负责写入和日志生成
Master 的核心职责不是“被读”,而是确保所有变更被可靠记录。它把每个事务的增删改操作写入 binary log,并维护一个位置指针(File + Position),告诉 Slave “我当前日志写到哪儿了”。这个日志是复制的唯一源头,所以:
- 必须开启 log-bin=mysql-bin,否则 Slave 连请求都发不出去;
- 必须设置唯一 server-id(如 server-id=1),否则 Slave 会拒绝连接;
- 所有写操作(INSERT/UPDATE/DELETE)必须发生在 Master,直接往 Slave 写会导致数据不一致,且无法自动修复。
从库(Slave)靠两个线程完成同步
Slave 不是被动接收数据,而是用两个独立线程分工协作:
- IO Thread:主动连 Master,请求指定位置之后的 binlog,收到后追加写入本地 relay-log,同时把最新读取位置记进 master.info(或 performance_schema 表);
- SQL Thread:持续读 relay-log,解析成 SQL 并重放——注意,它是串行执行的,所以主库并行写的事务,在从库可能变慢、甚至卡住;
常见问题包括:
- Seconds_Behind_Master 持续增长 → 通常是 SQL Thread 跟不上,比如大事务、锁表、磁盘 I/O 瓶颈;
- Slave_IO_Running: No → 网络不通、复制用户权限不足、Master 的 binlog 被清空(expire_logs_days 设置过小);
- Slave_SQL_Running: No → 从库有同名表、主键冲突、DDL 不兼容(如主库加字段,从库没加)。
角色不可互换,但可动态切换
默认架构下,Master 和 Slave 角色是硬编码在配置里的:
- Slave 的 CHANGE MASTER TO 命令里明确写了 MASTER_HOST、MASTER_USER 等,指向唯一 Master;
- Master 完全不知道自己有几个 Slave,也不感知它们的状态;
但实际运维中,角色可以切换:
- 故障时手动提升 Slave 为新 Master(需先 STOP SLAVE,再 RESET MASTER,再让其他节点 CHANGE MASTER TO 指向它);
- 主主(Master-Master)其实是两个节点互为 Master 和 Slave,但必须严格规避自增主键冲突(auto_increment_offset + auto_increment_increment 配合);
- 多主一从(Multi-source Replication)要求 MySQL ≥5.7,且每个 Master 必须有不同 server-id,否则 relay-log 会混。
为什么不能跳过角色设计直接用读写分离中间件?
有些团队想绕过主从配置,直接用 ShardingSphere 或 MaxScale 做自动路由,结果发现:
- 中间件不解决数据一致性,它只是转发请求;
- 如果底层没有可靠的 Master-Slave 复制链路,读到的就是过期或错误数据;
- binlog_format 设为 MIXED 或 ROW 是强依赖,语句级复制(STATEMENT)在函数、临时表、非确定性语句下大概率出错;
- 从库延迟超过阈值时,中间件若不做 read-after-write 路由控制,用户刚提交就查不到自己刚写的内容——这不是中间件的锅,是复制链路本身没兜住。
角色划分不是为了形式,而是把“谁记日志”“谁重放日志”“谁允许写”这些责任切得足够清晰。一旦混淆,比如在 Slave 上执行 DROP TABLE,或者误删 Master 的 binlog 文件,恢复成本远高于重新搭一套。










