主从复制原理
问题
MySQL 主从复制的原理是什么?binlog 有几种格式?GTID 和传统复制有什么区别?
答案
主从复制原理
三个关键线程:
- Master Binlog Dump Thread:主库发送 binlog 给从库
- Slave IO Thread:从库接收 binlog,写入 relay log
- Slave SQL Thread:从库重放 relay log 中的事件
Binlog 格式
| 格式 | 记录内容 | 优势 | 劣势 |
|---|---|---|---|
| STATEMENT | 原始 SQL 语句 | 日志量小 | 不确定函数(NOW/RAND)不安全 |
| ROW | 每行数据的变更 | 精确、安全 | 日志量大 |
| MIXED | 智能混合 | 兼顾优势 | 实现复杂 |
推荐
生产环境推荐 ROW 格式:虽然日志量大,但能保证主从数据一致。MySQL 8.0 默认使用 ROW。
复制模式
异步复制(默认)
问题:主库提交后立即返回,如果主库崩溃,已提交但未同步到从库的数据会丢失。
半同步复制(Semi-Sync)
至少一个从库确认收到 binlog 后,主库才返回成功。如果超时(默认 10s),自动降级为异步复制。
-- 主库开启半同步
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;
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 = 1;
全同步复制
所有从库都确认后才返回。性能最差,很少使用。MySQL Group Replication 提供了类似的强一致方案。
GTID 复制
GTID(Global Transaction ID)是 MySQL 5.6 引入的全局事务标识符:
GTID = server_uuid:transaction_id
例如:3E11FA47-71CA-11E1-9E33-C80AA9429562:23
| 对比 | 传统复制 | GTID 复制 |
|---|---|---|
| 定位 | binlog 文件名 + 偏移量 | GTID |
| 切换主库 | 需计算偏移量 | 自动定位 |
| 一致性 | 手动保证 | GTID 保证不重复执行 |
| 配置 | 复杂 | 简单 |
-- 开启 GTID(my.cnf)
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- 配置从库使用 GTID
CHANGE MASTER TO
MASTER_HOST = '192.168.1.1',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'password',
MASTER_AUTO_POSITION = 1; -- GTID 自动定位
主从延迟
主从延迟是最常见的运维问题:
延迟原因:
| 原因 | 说明 |
|---|---|
| 从库单线程回放 | 主库并发写入,从库单 SQL 线程串行回放 |
| 大事务 | 一个大 DELETE/UPDATE 在从库回放很慢 |
| 从库性能差 | 从库硬件配置低于主库 |
| 网络延迟 | 主从跨机房/跨地域 |
监控延迟:
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 主从延迟秒数
-- 0 = 无延迟,NULL = 复制断开
优化手段:
- 多线程复制(MySQL 5.7+):
SET GLOBAL slave_parallel_workers = 8;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
- 避免大事务:分批执行大 UPDATE/DELETE
- 从库升级硬件:SSD、更多内存
- 业务容忍:写后读强制走主库
常见面试问题
Q1: 主从复制有几种模式?区别是什么?
答案:
| 模式 | 数据安全 | 性能 | 说明 |
|---|---|---|---|
| 异步复制 | 可能丢数据 | 最好 | 默认模式 |
| 半同步复制 | 至少一个从库收到 | 略慢 | 推荐生产使用 |
| 全同步复制 | 所有从库确认 | 最慢 | 很少使用 |
Q2: binlog 的 ROW 和 STATEMENT 格式怎么选?
答案:
推荐 ROW 格式:
- STATEMENT 格式对不确定函数(
NOW()、UUID())可能导致主从不一致 - ROW 格式记录每行的修改,保证精确一致
- MySQL 8.0 默认 ROW
- 缺点是日志量大,可用
binlog_row_image=MINIMAL只记录变更列
Q3: GTID 复制相比传统复制有什么优势?
答案:
- 主从切换简单:不需要计算 binlog 位置,GTID 自动定位
- 一致性保证:同一 GTID 不会在从库重复执行
- 故障恢复快:从库知道自己执行到哪个 GTID,重新同步时自动跳过已执行的
- 更易运维:MHA/Orchestrator 等工具基于 GTID 更容易实现高可用切换
Q4: 如何解决主从延迟?
答案:
- 多线程复制:开启
slave_parallel_workers,按事务组并行回放 - 避免大事务:大 DML 分批执行
- 写后读走主库:关键业务写入后立即读取时,强制查主库
- 升级硬件:从库用 SSD
- 减少从库负载:避免在从库上执行重查询