MySQL 主从复制(Replication)是其最核心的高可用性和扩展性功能之一。它的原理是将一个 MySQL 实例(称为主库 Master)的数据变更,自动同步到另一个或多个 MySQL 实例(称为从库 Slave)的过程。
下面我将详细解析其工作原理、核心组件和流程。
一、 核心架构与组件
MySQL 主从复制是一个 “异步” 的、基于日志的复制系统,主要涉及三个线程和两种日志:
角色 | 组件 | 说明 |
主库 (Master) | Binary Log (binlog) | 核心。记录所有对数据库结构和内容进行修改的 SQL 语句(或实际数据行变更)。 |
Binlog Dump Thread | 主库上的一个线程,负责读取 binlog 并将其发送给从库的 I/O 线程。 | |
从库 (Slave) | I/O Thread | 从库上的线程,负责连接主库,请求和接收 binlog 数据,并将其写入本地的中继日志。 |
Relay Log | 从库上的一个日志文件,作为主库 binlog 的临时中转站和缓冲区。 | |
SQL Thread | 从库上的线程,负责读取中继日志中的内容,并解析执行其中的 SQL 语句,最终使从库数据与主库保持一致。 |
二、 主从复制的工作原理(三步流程)
整个过程可以清晰地分为三个步骤,下图直观地展示了这一流程:
flowchart TD
A[Client Write Request] --> B[Master Database]subgraph Master[Master Server]B --> C[Write Data<br>Update/Insert/Delete]C --> D[Write Binary Log<br>[binlog]]D --> E[Binlog Dump Thread]
endE -- "Binlog Events" --> F[I/O Thread]subgraph Slave[Slave Server]F --> G[Write Relay Log<br>[relay log]]G --> H[SQL Thread]H --> I[Replay Events]I --> J[Slave Data Updated]
end
步骤一:主库记录二进制日志 (Binary Log)
- 应用程序向主库发起数据变更请求(如
INSERT
, UPDATE
, DELETE
)。 - 主库执行完这些事务后,并不会立即返回,而是将这些更改事件按照一定的格式(
STATEMENT
, ROW
, MIXED
)写入到自己的 Binary Log 文件中。
- 注意:只有写操作会被记录,读操作不会。
步骤二:从库请求并接收日志 (I/O Thread)
- 从库的 I/O 线程会启动一个到主库的客户端连接。
- I/O 线程向主库的 Binlog Dump 线程发送一个请求,指定从哪个 binlog 文件的哪个位置开始同步。
- 主库的 Binlog Dump 线程读取 binlog 内容,并通过之前建立的连接发送给从库。
- 从库的 I/O 线程接收到这些 binlog 事件后,会将其顺序地写入到本地的 Relay Log 文件中。
步骤三:从库重放中继日志 (SQL Thread)
- 从库的 SQL 线程会不断地读取 Relay Log 文件中的事件。
- SQL 线程会解析并执行这些事件中的 SQL 语句(或者在
ROW
格式下,直接应用数据行的变化),从而在从库上重现主库上的操作。 - 一旦 SQL 线程执行完一个事件,它就会更新自己的
master.info
和 relay-log.info
文件,记录当前读取到的主库 binlog 位置,以便中断后能从正确的位置继续复制。
总结来说,从库通过两个线程实现了“接收日志”和“执行日志”的解耦:I/O 线程负责从主库拉取数据,SQL 线程负责消费这些数据。Relay Log 作为中间的缓冲区,使得两个线程可以独立工作,提高了复制的效率和稳定性。
三、 复制的格式 (Binlog Format)
这是理解复制行为和排查问题的关键。主库记录 binlog 有三种格式:
格式 | 原理 | 优点 | 缺点 |
STATEMENT (SBR) | 记录原始的 SQL 语句。 | 日志文件小,节省磁盘和网络 I/O。 | 可能因上下文信息(如系统变量、触发器)导致主从数据不一致。 |
ROW (RBR) | 记录每行数据如何被修改(修改前镜像/修改后镜像)。 | 安全可靠,几乎可以保证主从数据绝对一致。这是默认推荐的格式。 | 日志文件大(例如一条 |
MIXED (MBR) | 混合模式。一般情况下使用 STATEMENT,但在可能造成不一致的场景下(如使用 | 兼顾了安全性和性能。 | 仍存在极小的不确定性。 |
四、 半同步复制 (Semi-Synchronous Replication)
上述默认的复制是完全异步的。这意味着:
- 主库提交事务并写入binlog后,立即返回给客户端成功。
- binlog 通过异步的方式发送给从库。
风险:如果主库在返回成功后、binlog还未发送到任何从库时就宕机了,虽然客户端认为成功了,但这个事务实际上丢失了。
半同步复制 为了解决这个问题而诞生:
- 主库在提交事务时,会等待至少一个从库的 I/O 线程确认已经接收到了这个事件的 binlog。
- 只有在收到确认后,主库才会返回成功给客户端。
- 如果超时(可配置)还未收到确认,复制会降级为异步模式,之后一旦有从库恢复,又会自动升级回半同步。
这就在性能和数据一致性之间提供了一个很好的折衷,确保了数据的冗余性。
五、 主从复制的应用场景
- 读写分离:主库处理写操作和实时性要求高的读操作,从库处理大量的分析报表类读操作,显著提升系统整体性能。
- 数据备份:在从库上进行备份,不会对主库造成任何压力。
- 高可用性和故障切换:主库宕机后,可以快速将一个从库提升为新的主库,减少系统停机时间。
- 地理分布:将数据同步到不同地理位置的从库,供当地用户访问,提升访问速度。
六、 总结与核心要点
- 基础原理:基于 Binlog,采用 “拉” 的异步模式。
- 三个线程:主库的 Binlog Dump,从库的 I/O 和 SQL。
- 两个日志:主库的 Binary Log,从库的 Relay Log。
- 核心流程:主库写Binlog -> 从库I/O线程拉取并写Relay Log -> 从库SQL线程重放Relay Log。
- 格式选择:推荐使用 ROW 格式,以保证数据一致性。
- 数据安全:对数据可靠性要求极高的场景,可使用半同步复制。
另外搭配便捷的MYSQL备份工具,可定时备份、异地备份,MYSQL导出导入。可本地连接LINUX里的MYSQL,简单便捷。可以大大地提高工作效率喔。