主从复制原理

一句话总结

主库写 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 线程逐条放,主从同步毕;

延迟在大事务,并行复制医。

相关链接