别再背概念!用故事彻底讲懂MySQL主从复制

60 阅读6分钟



大家好,我是小米,一个爱喝冰美式、敲代码比打字还快的程序员。

上周,一个刚拿到社招面试机会的朋友找我求助:

“小米,我面试被问到:MySQL的主从复制原理和流程,你能讲讲吗?我当时脑子一片空白,只想到binlog,但细节都说不出来...”

哈哈,这一题太经典了。别说你,连我当年第一次被问到时,也是一脸懵逼。

今天我们就用一个故事,把这道高频面试题彻底讲清楚。

故事从“主从架构”开始

想象一下,公司有一台数据库服务器叫 Master(主库) ,负责所有的写操作

但随着用户越来越多,主库压力越来越大,慢查询、锁等待接连出现。

于是我们决定再加几台 Slave(从库) ,让它们专门用来读操作,实现“读写分离”。

这时候问题就来了:

  • 数据怎么从主库同步到从库?
  • 从库怎么知道主库更新了哪些数据?

这背后,正是MySQL复制机制(Replication) 的灵魂所在。

MySQL复制的“三步走”

MySQL的复制核心是一个“流水线”,由三个阶段组成:

  • 主库写 binlog(二进制日志)
  • 从库读取主库的 binlog
  • 从库执行 relay log(中继日志)重放变更

听上去简单,但每一步都有不少玄机。

第一步:主库记录 binlog

当主库执行一条写入语句,比如:

这条SQL不仅会修改主库数据页,还会被记录进一个叫 binlog(Binary Log) 的文件里。

binlog记录了数据库所有的变化事件(Insert、Update、Delete等),是主从同步数据恢复的基础。

每一条binlog事件都包含:

  • 事件类型:比如update_rows、write_rows
  • 变更内容:修改了哪张表、哪条记录
  • 事务信息:事务开始与提交的标识

简单说,主库把自己执行的“操作脚本”写进了binlog,为从库“抄作业”做准备。

第二步:从库I/O线程拉取binlog

从库要想同步数据,得知道主库更新了什么。

于是,从库启动后,会在后台启动一个 I/O线程,主动连上主库,请求binlog。

它会告诉主库:“我上次同步到了文件mysql-bin.000005的第120行,从那以后更新的部分发我看看。”

主库接到请求后,会派出一个 Binlog Dump 线程,负责把后续binlog内容一条条发给从库。

I/O线程收到后,不会立刻执行,而是先把内容写入本地的 relay log(中继日志) 文件。

这就好比你先抄下老师黑板上的笔记,还没开始做题。

第三步:从库SQL线程重放relay log

接下来,另一位主角登场——从库的 SQL线程

它负责读取relay log中的内容,顺序执行这些变更,最终让从库的数据与主库保持一致。

就这样,一个完整的同步流程结束。所以,MySQL复制的三大线程模型是这样的:

复制的模式:三种方式各有妙用

MySQL支持三种复制方式,不同模式对应不同性能和一致性要求。

1、基于语句的复制(Statement-Based Replication, SBR)

主库把SQL语句本身写进binlog,从库执行相同SQL。

优点:

  • 日志量小,传输快
  • 可读性好

缺点:

  • 对“非确定性语句”不友好(比如 RAND()、NOW())
  • 可能出现主从不一致

2、基于行的复制(Row-Based Replication, RBR)

主库不记录SQL,而是直接记录被修改的行数据。比如上面的 UPDATE,它会记录修改前和修改后的行。

优点:

  • 精确、可靠,保证主从数据一致性
  • 适合大多数生产环境

缺点:

  • binlog体积大,占带宽

3、混合模式(Mixed-Based Replication, MBR)

MySQL会自动判断该用哪种方式:

  • 对确定性语句用SBR
  • 对复杂语句用RBR

算是兼顾性能和一致性的“折中方案”,MySQL 8.x默认推荐这种。

复制的延迟:那点“小问题”

如果你在主库插入一条记录,然后立刻去从库查,发现还没出现——别慌。

这就是主从延迟。延迟的原因有很多,比如:

  • 网络延迟(主从之间传输慢)
  • 从库I/O或SQL线程处理不及时
  • 主库高并发、大事务
  • 从库硬件性能

举个真实例子:

有一次我们线上做一次大批量删除操作,结果从库延迟了整整5分钟,监控报警不停闪。

后来我们通过优化事务大小、开启多线程复制(MySQL 8.x支持多线程SQL线程),才彻底缓解了这个问题。

MySQL 8.x的新特性:复制更聪明了

MySQL 8.x对复制机制做了不少优化,让主从架构更稳定、更快。

1. 多线程复制(MTS)增强

  • 从库可以按库、按表甚至按事务并行执行relay log,极大提升同步速度。

2. GTID(全局事务ID)支持

  • MySQL 8.x默认支持GTID,每个事务都有唯一ID。
  • 从库可以自动定位同步位置,再也不用手动指定binlog文件名+位置号。

3. 延迟复制(Delayed Replication)

  • 可以设置从库延迟执行主库的事务,比如延迟10分钟执行。
  • 用于防止误操作(主库误删后还有机会从延迟从库恢复)。

4. 异步与半同步复制(Semi-sync)

  • 半同步复制让主库在提交事务时,至少等一台从库确认收到binlog后再返回成功,提升数据安全性。

总结:从面试到实战

现在我们再回头看看面试题:

面试官:你能讲讲MySQL的复制原理和流程吗?

你可以这样答:

MySQL复制通过主库binlog和从库relay log实现数据同步。

整个过程分三步:主库记录binlog,从库I/O线程拉取并保存为relay log,SQL线程重放日志。

常见的复制模式有基于语句、基于行和混合模式,MySQL 8.x支持GTID、多线程复制和半同步复制,提升了性能和一致性。

一句话讲完——MySQL复制,其实就是一场“日志接力赛”。

彩蛋:面试官可能的追问

Q1:MySQL复制是实时的吗?

A:不是实时同步,而是“准实时”,可能有轻微延迟。

Q2:主从延迟怎么优化?

A:优化SQL语句、缩小事务、提高从库性能、开启多线程复制。

Q3:主从复制能不能保证强一致性?

A:默认是最终一致性。如果要强一致,可以使用半同步复制(Semi-sync)。

结语

如果把数据库比作公司员工,主库是那个写日报的组长,从库是几个抄日报的实习生。

只要组长写得快、抄得勤,整个团队的数据就能同步如一。

面试问MySQL复制原理,不是要你背定义,而是看你懂不懂它的运行机制和演化逻辑

理解了这条“日志接力链”,不仅能轻松拿下面试,还能在项目中真正用好它。

END

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!