MySQL 主从复制原理是什么?

2025年 阅读约 15 分钟 面试指南 · MySQL

深入解析MySQL主从复制原理:binlog三种格式(STATEMENT/ROW/MIXED)、GTID复制、半同步复制、读写分离方案、主从延迟原因与解决方案,附实战配置和面试模拟问答。

一句话总结

MySQL 主从复制基于 binlog,分三步:1)主库写 binlog2)从库 IO 线程拉取 binlog 写入 relay log3)从库 SQL 线程重放 relay log。binlog 有三种格式:STATEMENT(记录 SQL)、ROW(记录行变更,推荐)、MIXED(混合)。GTID 复制简化了主从切换。主从延迟是常见问题,原因包括从库性能差、大事务、网络延迟。

初级理解

主从复制三步流程

1. 主库写入 binlog:事务提交时,主库将数据变更写入 binlog

2. 从库 IO 线程拉取:从库 IO 线程连接主库,读取 binlog 并写入 relay log(中继日志)

3. 从库 SQL 线程重放:从库 SQL 线程读取 relay log 中的事件,在从库上重放执行

binlog 三种格式对比

格式记录内容优点缺点
STATEMENTSQL 语句日志量小部分函数(NOW/UUID)导致主从不一致
ROW(推荐)每行数据变更精确,不会不一致日志量大(UPDATE 全表时)
MIXED默认 STATEMENT,特殊时 ROW折中方案仍有不一致风险
# 查看 binlog 格式 SHOW VARIABLES LIKE 'binlog_format'; # 设置 binlog 格式 SET GLOBAL binlog_format = 'ROW'; # 查看 binlog 文件列表 SHOW BINARY LOGS; # 查看 binlog 内容 SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 10; # 用 mysqlbinlog 工具解析 mysqlbinlog --base64-output=decode-rows -v mysql-bin.000001
一句话总结:主从复制 = 主库写 binlog → 从库 IO 线程拉 → 从库 SQL 线程放,ROW 格式最安全。

中级深入

GTID 复制(MySQL 5.6+)

GTID(Global Transaction Identifier)是事务的全局唯一标识,格式:server_uuid:transaction_id。相比传统基于 binlog 文件名+位置的复制,GTID 简化了主从切换,从库自动找同步点。

# 开启 GTID(my.cnf) [mysqld] gtid_mode = ON enforce_gtid_consistency = ON # 从库配置 GTID 复制 CHANGE MASTER TO MASTER_HOST = '192.168.1.100', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = 'password', MASTER_AUTO_POSITION = 1; # 自动找同步位置 # 查看 GTID 执行情况 SHOW MASTER STATUS\G SHOW SLAVE STATUS\G # Executed_Gtid_Set: 已执行的 GTID 集合 # Retrieved_Gtid_Set: 已接收的 GTID 集合

半同步复制 — 解决数据丢失

默认异步复制:主库提交后立即返回,不等待从库确认 → 主库宕机可能丢数据。

半同步复制:主库提交后等待至少一个从库收到 binlog 并写入 relay log后才返回客户端。

# 安装半同步插件 # 主库 INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; SET GLOBAL rpl_semi_sync_master_enabled = ON; SET GLOBAL rpl_semi_sync_master_timeout = 10000; # 超时 10 秒退化为异步 # 从库 INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; SET GLOBAL rpl_semi_sync_slave_enabled = ON; # 查看半同步状态 SHOW STATUS LIKE 'Rpl_semi_sync%';

主从延迟原因与解决

原因解决方案
从库性能差(配置低)从库配置不低于主库
大事务(一次更新百万行)拆分大事务为小事务
从库 SQL 线程单线程(5.6 前)MySQL 5.7+ 并行复制(MTS)
网络延迟主从同机房部署
锁等待减少从库上的查询负载
# 查看主从延迟 SHOW SLAVE STATUS\G # Seconds_Behind_Master: 延迟秒数(NULL 表示复制异常) # 开启并行复制(MySQL 5.7+) SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; SET GLOBAL slave_parallel_workers = 4; # 4 个并行线程 # 监控延迟 SELECT * FROM performance_schema.replication_applier_status_by_worker;
中级要点:GTID 简化主从切换;半同步减少数据丢失;并行复制(MTS)缓解延迟。

高级拓展

读写分离方案

方案实现优点缺点
客户端路由ShardingSphere-JDBC无额外组件,性能好语言绑定,配置复杂
中间件代理ProxySQL / MySQL Router对应用透明多一层网络开销
DNS 轮询读域名指向多个从库简单无感知延迟和故障
# ShardingSphere-JDBC 读写分离配置(Spring Boot) # application.yml spring: shardingsphere: datasource: names: master, slave0, slave1 master: type: com.zaxxer.hikari.HikariDataSource url: jdbc:mysql://master:3306/db slave0: url: jdbc:mysql://slave0:3306/db slave1: url: jdbc:mysql://slave1:3306/db rules: readwrite-splitting: data-sources: myds: type: Static props: write-data-source-name: master read-data-source-names: slave0, slave1 load-balancer-name: round_robin

主从切换(Failover)

当主库宕机时,需要将一个从库提升为主库。传统方式手动切换,推荐使用 OrchestratorMHA 自动切换。

# 手动主从切换步骤 # 1. 确认主库已宕机,所有从库已同步到最新 # 2. 选择一个数据最新的从库作为新主库 # 3. 在新主库上: STOP SLAVE; RESET SLAVE ALL; # 4. 其他从库指向新主库: CHANGE MASTER TO MASTER_HOST='新主库IP', MASTER_AUTO_POSITION=1; START SLAVE; # 5. 更新应用连接地址

实战场景

场景:搭建一主一从复制

# 主库配置(my.cnf) [mysqld] server-id = 1 log-bin = mysql-bin binlog_format = ROW binlog_row_image = FULL expire_logs_days = 7 # 主库创建复制用户 CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES; # 主库备份并记录位置 FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS; # 记录 File 和 Position mysqldump -u root -p --all-databases --master-data > backup.sql UNLOCK TABLES; # 从库配置(my.cnf) [mysqld] server-id = 2 relay-log = relay-log read_only = ON # 从库导入备份 mysql -u root -p < backup.sql # 从库配置复制 CHANGE MASTER TO MASTER_HOST = '192.168.1.100', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = 'repl_password', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 1234; START SLAVE; SHOW SLAVE STATUS\G # 确认 Slave_IO_Running 和 Slave_SQL_Running 都是 Yes

面试模拟

面试官:主从延迟怎么解决?

你:1)MySQL 5.7+ 开启并行复制(MTS),设置 slave_parallel_workers;2)拆分大事务,避免一次更新百万行;3)从库硬件配置不低于主库;4)主从同机房部署减少网络延迟;5)业务上容忍延迟——关键读走主库,非关键读走从库。

面试官:binlog 的 ROW 和 STATEMENT 格式有什么区别?

你:STATEMENT 记录 SQL 语句,日志量小但可能主从不一致(如 NOW()、UUID() 等函数);ROW 记录每行数据变更,日志量大但精确安全。生产环境推荐 ROW 格式,MySQL 8.0 默认也是 ROW。

面试官:GTID 复制有什么优势?

你:1)简化主从切换——不需要手动指定 binlog 文件和位置,MASTER_AUTO_POSITION=1 自动找同步点;2)每个事务有全局唯一 ID,方便追踪;3)支持多源复制和级联复制时更易管理。