问题
MySQL主从复制的架构和实现方式是什么?
答案
核心概念
MySQL主从复制(Master-Slave Replication)是一种数据同步技术,通过将主库的数据变更复制到一个或多个从库,实现数据备份、读写分离、高可用等目标。
主从复制的架构
1. 一主多从架构(最常见)
主库(Master)
/ | \
/ | \
从库1 从库2 从库3
(Slave) (Slave) (Slave)
特点:
- 主库负责写入
- 从库负责读取(读写分离)
- 可横向扩展从库提升读性能
2. 级联复制架构
主库(Master)
↓
从库1(Slave & Master)
/ \
从库2 从库3
特点:
- 减轻主库复制压力
- 从库1既是从库也是其他从库的主库
- 延迟会累加
3. 双主复制(互为主从)
主库A ←→ 主库B
(互为主从)
特点:
- 两个库都可写
- 需要避免主键冲突(自增步长错开)
- 存在数据冲突风险
复制的完整流程
主库(Master) 从库(Slave)
| |
1. 执行SQL语句 |
↓ |
2. 写入binlog |
↓ |
3. [Dump Thread] --------binlog----→ 4. [IO Thread]
↓
5. 写入relay log
↓
6. [SQL Thread]
↓
7. 执行SQL,同步数据
三个核心线程:
- Binlog Dump Thread(主库):读取binlog并发送给从库
- IO Thread(从库):接收binlog并写入relay log
- SQL Thread(从库):读取relay log并执行SQL
主从复制的配置
1. 主库配置
my.cnf配置:
[mysqld]
# 开启binlog
log-bin=mysql-bin
# 服务器唯一ID(集群内不重复)
server-id=1
# binlog格式(ROW推荐)
binlog_format=ROW
# binlog保留时间(秒)
expire_logs_days=7
# 需要复制的数据库(可选)
binlog-do-db=mydb
# 不需要复制的数据库(可选)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
创建复制账号:
-- 创建专用复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
-- 查看主库状态
SHOW MASTER STATUS;
-- 记录File和Position,从库需要用到
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 154 | | |
+------------------+----------+--------------+------------------+
2. 从库配置
my.cnf配置:
[mysqld]
# 服务器唯一ID(与主库不同)
server-id=2
# 开启relay log
relay-log=mysql-relay-bin
# 从库只读(可选,推荐)
read_only=1
# super用户仍可写(更安全)
super_read_only=1
# relay log自动恢复
relay_log_recovery=ON
# 并行复制(MySQL 5.7+)
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=4
配置复制关系:
-- 停止从库(如果已启动)
STOP SLAVE;
-- 配置主库信息
CHANGE MASTER TO
MASTER_HOST='192.168.1.100', -- 主库IP
MASTER_PORT=3306, -- 主库端口
MASTER_USER='repl', -- 复制用户
MASTER_PASSWORD='Repl@123456', -- 复制密码
MASTER_LOG_FILE='mysql-bin.000003', -- 主库binlog文件
MASTER_LOG_POS=154; -- 主库binlog位置
-- 启动从库
START SLAVE;
-- 查看从库状态
SHOW SLAVE STATUS\G
-- 关键指标
Slave_IO_Running: Yes -- IO线程运行正常
Slave_SQL_Running: Yes -- SQL线程运行正常
Seconds_Behind_Master: 0 -- 延迟秒数
Last_IO_Error: -- IO错误信息
Last_SQL_Error: -- SQL错误信息
基于GTID的复制(推荐)
GTID(Global Transaction Identifier)是全局事务ID,MySQL 5.6+支持,简化复制配置。
GTID的优势
- 无需手动指定binlog文件和位置
- 主库切换更简单
- 自动跳过已执行的事务
- 更容易搭建复杂拓扑
配置GTID复制
主库配置:
[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=ROW
# 开启GTID
gtid_mode=ON
enforce_gtid_consistency=ON
从库配置:
[mysqld]
server-id=2
relay-log=mysql-relay-bin
# 开启GTID
gtid_mode=ON
enforce_gtid_consistency=ON
从库配置复制:
-- 基于GTID的复制配置(无需指定binlog文件和位置)
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123456',
MASTER_AUTO_POSITION=1; -- 使用GTID自动定位
START SLAVE;
查看GTID信息:
-- 主库查看已执行的GTID集合
SHOW MASTER STATUS;
-- Executed_Gtid_Set: 3e11fa47-71ca-11e5-9e11-fa163e6dd4e8:1-20
-- 从库查看已接收和已执行的GTID
SHOW SLAVE STATUS\G
-- Retrieved_Gtid_Set: 3e11fa47-71ca-11e5-9e11-fa163e6dd4e8:1-20
-- Executed_Gtid_Set: 3e11fa47-71ca-11e5-9e11-fa163e6dd4e8:1-20
三种复制模式
1. 异步复制(默认)
主库 --写入binlog--> 立即返回
↓
从库(异步拉取)
特点:
- 性能最高
- 主库宕机可能丢数据
- 存在主从延迟
2. 半同步复制
主库 --写入binlog--> 等待至少1个从库确认 --> 返回
↓
从库(确认接收)
配置:
-- 主库安装插件
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 = 1000; -- 超时1秒降级
-- 从库安装插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
特点:
- 更高的数据可靠性
- 轻微性能损失
- 超时后自动降级为异步
3. 全同步复制(MGR)
主库 --写入binlog--> 等待多数节点确认 --> 返回
↓
多数派从库(Paxos共识)
特点:
- 强一致性
- 性能损失较大
- 适合金融等高一致场景
应用场景
1. 读写分离
@Configuration
public class DataSourceConfig {
@Bean
public DataSource masterDataSource() {
// 主库:写操作
return DataSourceBuilder.create()
.url("jdbc:mysql://master:3306/db")
.build();
}
@Bean
public DataSource slaveDataSource() {
// 从库:读操作
return DataSourceBuilder.create()
.url("jdbc:mysql://slave:3306/db")
.build();
}
}
@Service
public class UserService {
@Master // 自定义注解,路由到主库
public void createUser(User user) {
userMapper.insert(user);
}
@Slave // 路由到从库
public List<User> listUsers() {
return userMapper.selectAll();
}
}
2. 数据备份
# 从库备份不影响主库
mysqldump -h slave -u backup -p --single-transaction mydb > backup.sql
3. 高可用切换
主库宕机 → MHA/Orchestrator检测 → 提升从库为主库 → 应用切换连接
常见问题排查
1. 复制中断
SHOW SLAVE STATUS\G
-- IO线程停止
Slave_IO_Running: No
Last_IO_Error: error connecting to master
-- 解决:检查网络、主库状态、账号权限
-- SQL线程停止
Slave_SQL_Running: No
Last_SQL_Error: Error 'Duplicate entry' on query
-- 解决:跳过错误事务或修复数据
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
2. 主从数据不一致
# 使用pt-table-checksum检测
pt-table-checksum --host=master --replicate=percona.checksums
# 使用pt-table-sync修复
pt-table-sync --execute --sync-to-master slave
3. 主从延迟过大
-- 查看延迟
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 120
-- 解决方案:
-- 1. 启用并行复制
-- 2. 升级从库硬件
-- 3. 优化慢SQL
-- 4. 使用半同步复制
面试答题总结
MySQL主从复制通过binlog记录、relay log中继、SQL线程重放三步实现数据同步。架构上常用一主多从实现读写分离。复制方式包括异步复制(默认)、半同步复制(更可靠)、全同步复制(强一致)。MySQL 5.6+推荐使用GTID模式,简化配置和主从切换。关键配置是主库开启binlog,从库指定主库信息并启动IO和SQL线程。生产环境需监控Slave_IO_Running、Slave_SQL_Running、Seconds_Behind_Master等指标,及时发现和处理复制中断、延迟等问题。