1、简述
在实际开发中,为了实现数据库读写分离、高可用容灾、数据备份等目标,MySQL 的主从复制(Master-Slave Replication)被广泛采用。主从复制可以让主库处理写操作,从库承担读请求,极大提升系统的并发能力和稳定性。
本文将全面解析 MySQL 主从复制的原理、流程、配置步骤以及 Java 应用中的实战案例,助你快速掌握并应用该能力。
2、什么是主从复制?
MySQL 主从复制是指:
主库将数据更改操作记录到
binlog
(二进制日志),从库通过I/O
线程拉取该日志,并通过SQL
线程在本地回放,实现数据的同步复制。
应用价值:
- 实现 读写分离,提升吞吐
- 实现 备份容灾,防止主库故障丢数据
- 支持 异地多活、分布式架构等扩展
3、主从复制的三大核心线程
-
主库:Binlog 写入线程
将所有数据变更记录写入 binary log(二进制日志)
-
从库:I/O 线程
向主库请求 binlog 日志
把日志写入本地 relay log(中继日志) -
从库:SQL 线程
读取 relay log 并执行 SQL 语句,实现数据同步
复制方式 | 特点 | 应用场景 |
---|---|---|
异步复制 | 默认模式,从库落后主库 | 延迟可接受系统 |
半同步复制 | 主库确认至少一个从库收到日志 | 增强一致性、性能权衡 |
全同步复制 | 所有从库同步后才确认 | 一致性强,但写入慢 |
4、主从复制配置流程(实践步骤)
4.1 主库配置
编辑主库 my.cnf
配置文件:
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-do-db=test_db # 可选,仅复制该数据库
重启 MySQL:
sudo systemctl restart mysql
创建复制账号:
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_pass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
查询当前 binlog 状态:
SHOW MASTER STATUS;
结果示例:
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB|
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 154 | test_db | |
+------------------+----------+--------------+------------------+
记录 File
和 Position
。
4.2 从库配置
编辑从库 my.cnf
:
[mysqld]
server-id=2
relay-log=relay-log
log-bin=mysql-slave-bin
read-only=1
重启 MySQL。
配置主库信息:
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl',
MASTER_PASSWORD='repl_pass',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
启动复制:
START SLAVE;
查看状态:
SHOW SLAVE STATUS\G
检查:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
即表示主从复制成功。
4.3 复制测试实践
主库插入数据
USE test_db;
INSERT INTO users(id, name) VALUES(1, 'Alice');
从库查询
SELECT * FROM test_db.users;
数据成功复制,主从复制验证通过。
5、实践样例:读写分离配置
基于 Spring Boot 多数据源配置,实现主库写、从库读。
5.1 application.yml
spring:
datasource:
master:
url: jdbc:mysql://master-host:3306/test_db
username: root
password: root
slave:
url: jdbc:mysql://slave-host:3306/test_db
username: root
password: root
5.2 自定义数据源路由
public enum DBType {
MASTER, SLAVE
}
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<DBType> context = new ThreadLocal<>();
public static void set(DBType type) { context.set(type); }
@Override
protected Object determineCurrentLookupKey() {
return context.get();
}
}
5.3 使用示例
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void createUser(User user) {
DynamicDataSource.set(DBType.MASTER);
userMapper.insert(user);
}
public User getUserById(Long id) {
DynamicDataSource.set(DBType.SLAVE);
return userMapper.selectById(id);
}
}
6、复制架构扩展方案
- 一主多从:主库写,从库负载均衡读
- 级联复制:从库再挂子从库,缓解主库压力
- 主主复制(双主):需防止数据冲突、循环复制
常见问题与建议:
问题 | 解决方案 |
---|---|
从库落后(同步延迟) | 使用 semi-sync、提升从库性能、开启并行复制 |
主库变更后未同步从库 | 检查 binlog、账号权限、网络 |
同步失败中断 | 查看 SHOW SLAVE STATUS 中的错误日志 |
写错从库(读写分离错误) | 设置从库只读、应用层做好数据源隔离 |
7、总结
MySQL 主从复制是构建高性能、可扩展数据库架构的基础能力。通过本文你应掌握:
✅ 主从复制的原理与三大线程
✅ 配置主从复制的全流程
✅ Java 应用中实现读写分离实践
✅ 多种复制模式与应对延迟的方法
如需进一步学习:
- Spring Boot 自动读写分离完整实战项目
- GTID 模式复制配置指南
- 基于 Canal 增量同步实战(结合 Kafka、ES)
是否需要我继续扩展?欢迎提问📩