主从复制原理
一句话总结
主库写 binlog → 从库拉 binlog → 从库重放。主库只管干活不等人,从库异步跟在后面抄作业。核心是三个线程:主库的 Dump 线程、从库的 IO 线程和 SQL 线程。
🌰 理解和类比
你是一家火锅店的总店长(主库),开了三家分店(从库)。
总店长(主库):
└─ 每天写工作日志(binlog)
└─ "今天卖了 300 锅,新进了 50 斤毛肚..."
分店长(从库):
每天早上来总店抄昨天的日志
└─ "哦,毛肚进货了,那今天也卖毛肚"
└─ 跟着总店的节奏走
-
总店长不等分店长——主库写完 binlog 就返回,不管从库有没有同步
-
分店长可能比总店长慢半拍——从库有延迟
-
如果总店长突然倒了——从库可以顶上成为新总店
架构:三个线程
graph LR subgraph Master["主库"] Write["业务请求 → 写 binlog"] Dump["Dump 线程<br/>(把 binlog 发给从库)"] Write --> Dump end Dump -->|"网络传输"| IO["IO 线程<br/>(拉 binlog 写 relay log)"] subgraph Slave["从库"] IO --> Relay["relay log(中继日志)"] Relay --> SQL["SQL 线程<br/>(重放 relay log)"] SQL --> Update["从库数据更新"] end
线程分工
| 线程 | 在哪 | 干什么 |
|---|---|---|
| Dump 线程 | 主库 | 监听 binlog 变更,推给连接的从库 |
| IO 线程 | 从库 | 连主库拉 binlog,写到本地的 relay log |
| SQL 线程 | 从库 | 读取 relay log,逐条重放 SQL |
三种复制模式
1. 异步复制(默认)
主库:写 binlog → 返回"成功" → 不管从库
从库:自己慢慢拉
✅ 主库性能最好(不等人)
❌ 主库崩了还没同步到从库 → 数据丢
2. 半同步复制(rpl_semi_sync)
主库:写 binlog → 等至少一个从库确认收到 → 返回"成功"
从库:收到 binlog 回 ACK
✅ 主库崩溃时数据不丢(至少一个从库有)
❌ 主库性能略降(多一次网络等待)
3. 全同步复制(MySQL Group Replication)
主库:写 binlog → 等所有从库确认 → 返回"成功"
✅ 数据绝对不丢
❌ 慢,一个从库挂了整个集群卡住
生产最常见:半同步复制。兼顾性能和安全性。
主从复制的核心流程
全量同步(从库第一次搭建)
从库刚搭好,数据为空。
Step 1: 主库执行 FLUSH TABLES WITH READ LOCK(全局只读锁)
Step 2: 主库记录当前 binlog 位置(文件名 + 偏移量)
Step 3: 主库导出全量数据(mysqldump)
Step 4: 解锁
Step 5: 从库导入全量数据
Step 6: 从库执行 CHANGE MASTER TO,指定 binlog 位置
Step 7: 从库开始复制(从这个位置往后拉 binlog)
增量同步(日常运行)
Step 1: 主库提交事务 → 写 binlog
Step 2: 主库 Dump 线程通知从库"有新 binlog"
Step 3: 从库 IO 线程拉取新 binlog 内容
Step 4: 从库 IO 线程写入 relay log
Step 5: 从库 SQL 线程读取 relay log
Step 6: 从库 SQL 线程逐条重放
Step 7: 从库数据更新
主从延迟(最头疼的问题)
为什么从库会落后?
主库写 1 万行数据:1 秒
从库重放 1 万行数据:3 秒
主库写入速度 > 从库重放速度 → 延迟越来越大
常见原因
| 原因 | 说明 |
|---|---|
| 从库单线程重放 | 主库多线程写,从库 SQL 线程单线程重放 |
| 从库硬件差 | 从库磁盘 IO 比主库慢 |
| 大事务 | 一个 DELETE FROM 删 100 万行,主库秒写完 binlog,从库要重放很久 |
| 从库也承担读请求 | 从库上还有查询在跑,抢 CPU 和 IO |
缓解方案
| 方案 | 效果 |
|---|---|
| 5.7+ 开启并行复制 | slave_parallel_workers > 0,多线程重放 |
| 主库升级硬件 | 从库硬件不低于主库 |
| 拆分大事务 | 100 万行分 100 批删,每批 1 万行 |
| 监控 Seconds_Behind_Master | 超过阈值报警 |
| 从库只做读分离 | 别在从库上跑分析查询 |
延迟的另一种解法
如果业务不能接受任何延迟 → 读写都在主库做
如果业务能接受秒级延迟 → 写入主库,读从库(典型方案)
如果业务需要强一致 → 刚写完从主库读,过一会儿再从从库读
主从复制话术
延伸提问:"说说 MySQL 主从复制的原理"
你:
"MySQL 主从复制基于 binlog。主库把变更写入 binlog,
从库通过 IO 线程拉取 binlog 写入 relay log,
SQL 线程再重放 relay log。
主库不会等从库,默认是异步的。
生产推荐半同步复制——等至少一个从库确认收到再返回。
三个关键指标:
1. Seconds_Behind_Master——从库落后主库多少秒
2. 并行复制是否开启——5.7 后多线程重放能大幅降低延迟
3. 大事务是延迟的头号杀手——尽量拆小"
记忆口诀
主库写 binlog,Dump 线程发出去。
从库 IO 线程收,relay log 存起来。
SQL 线程逐条放,主库同步就完成。
延迟主要在大事务和单线程重放,并行复制能解决大半。
速记卡(面试闪卡)
Q1:一句话讲清「主从复制原理」到底是什么?
A:主从复制基于 binlog:主库写日志,从库 IO 线程拉取、SQL 线程重放,核心是三个线程。
Q2:🌰 理解和类比 —— 怎么理解?
A:像”火锅总店与分店”:总店长(主库)每天写工作日志(binlog)就返回,不等分店;分店长(从库)早上来抄日志、跟着总店节奏走,可能慢半拍(延迟);总店倒了分店能顶上。主库只管干活不等人,从库异步跟在后面抄作业。
Q3:架构:三个线程 —— 怎么理解?
A:三个”快递员”分工:Dump 线程(主库)监听 binlog 变更、推给从库;IO 线程(从库)连主库拉 binlog、写到本地 relay log(中继日志);SQL 线程(从库)读 relay log 逐条重放。一推一拉一放,数据就同步了。
Q4:三种复制模式 —— 怎么理解?
A:三种”等多久”:异步(默认)主库写完就返回,性能最好但崩了可能丢数据;半同步等至少一个从库确认收到再返回,兼顾性能与安全,生产最常见;全同步等所有从库确认,绝对不丢但慢、一个挂全卡。
Q5:主从复制的核心流程 —— 怎么理解?
A:日常增量七步:主库提交写 binlog → Dump 通知 → 从库 IO 拉取写 relay log → SQL 线程读 relay log → 逐条重放 → 从库数据更新。首次搭建则先全量导出(mysqldump)+ 记 binlog 位置,再从此往后拉。
Q6:核心速记主线有哪些?
-
主库写 binlog,Dump 线程推给从库
-
从库 IO 线程拉 binlog 写 relay log
-
SQL 线程重放 relay log 完成同步
-
默认异步,生产推荐半同步复制
口诀
A:主库写 binlog,Dump 发出去;
从库 IO 收,relay log 存起。
SQL 线程逐条放,主从同步毕;
延迟在大事务,并行复制医。