📌关键词:主从复制、读写分离、binlog、高可用、数据安全、运维进阶
大家好呀!我是数据库小学妹👋
前面我们学了很多优化技巧:索引、分区表、慢查询定位……都是在让单台数据库跑得更快。但现实世界中,数据库就像公司的核心资产,如果这台机器突然“罢工”(宕机)了,或者数据被人误删了,那可就是灾难性的事故。
有没有一种方案,能让多台数据库服务器协同工作,分担读写压力,还能在一台机器宕机时自动切换?
这就是主从复制。简单来说,它就像是给你的数据库找了一个“影分身”,主库负责干活,从库负责“照镜子”,既保证了数据不丢失,又能让你的系统扛住更大的流量!
一、什么是主从复制?
主从复制是指将主数据库(Master)的数据变更,实时同步到一个或多个从数据库(Slave)上。
- 主库(Master):负责写操作(INSERT/UPDATE/DELETE),也可以读。
- 从库(Slave):负责读操作(SELECT),并持续从主库同步数据。
🚩核心价值:
- 数据安全(灾备):主库挂了,从库有全量数据,随时可以顶上。
- 读写分离(性能扩展):将读压力分摊到多个从库上,解决“读多写少”场景的性能瓶颈。
- 数据分布:比如成都的用户连成都的库,北京的用户连北京的库(异地多活的基础)。
二、主从复制的原理(三个线程)
MySQL主从复制基于二进制日志(binlog),主要涉及三个线程:
- 主库的 Binlog Dump 线程:主库将变更写入 binlog,并发送给从库。
- 从库的 I/O 线程:从库连接到主库,请求 binlog,并写入自己的中继日志(relay log)。
- 从库的 SQL 线程:从中继日志读取事件,在从库上重放执行。
flowchart LR
Master[(主库)] -->|binlog| Slave_IO[从库I/O线程]
Slave_IO -->|写入| Relay_Log[(中继日志)]
Relay_Log -->|读取重放| Slave_SQL[从库SQL线程]
Slave_SQL --> Slave_DB[(从库)]
一句话总结:主库写日志,从库拉日志、放日志、执行日志。
三、主从复制的三种常见模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 异步复制(默认) | 主库执行完事务立即返回,不等待从库确认 | 性能最高,但可能丢数据 |
| 半同步复制 | 主库等待至少一个从库收到binlog后才提交 | 平衡性能和数据安全 |
| 全同步复制 | 主库等待所有从库执行完才提交 | 数据最安全,性能最差(极少用) |
💡 实际生产中,半同步复制用得最多,既保证了一致性,又不过分牺牲性能。
四、快速搭建主从复制(示例)
环境准备
- 主库 IP:192.168.1.10
- 从库 IP:192.168.1.11
- MySQL 版本:8.0
1. 配置主库(my.cnf)
[mysqld]
log-bin=mysql-bin # 开启binlog
server-id=1 # 主库唯一ID
binlog-format=ROW # 推荐ROW格式
重启MySQL,创建复制用户:
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
查看主库状态:
SHOW MASTER STATUS;
-- 记录 File 和 Position,如 mysql-bin.000001,Position=123
2. 配置从库(my.cnf)
[mysqld]
server-id=2 # 从库唯一ID,不能和主库重复
relay-log=relay-bin # 中继日志
read_only=1 # 从库只读(可选)
重启从库,设置复制信息:
CHANGE MASTER TO
MASTER_HOST='192.168.1.10',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=123;
START SLAVE;
3. 检查复制状态
SHOW SLAVE STATUS\G
重点关注:
Slave_IO_Running= YesSlave_SQL_Running= Yes
都显示Yes,说明复制正常。
五、读写分离:怎么让应用分流?
搭建好主从后,需要在应用层实现读写分离。常见方案:
| 方案 | 说明 |
|---|---|
| 中间件 | MyCAT、ShardingSphere-Proxy、ProxySQL |
| 框架支持 | Spring Boot 动态数据源(如@Transactional注解) |
| 手动路由 | 代码中判断SQL类型,切换数据源 |
💡 新手可以先在本地用 Spring Boot + HikariCP + 注解 模拟读写分离,了解原理。
六、主从复制的延迟问题
延迟是指从库执行SQL落后于主库的时间。原因可能包括:
- 从库硬件配置低
- 主库写入压力过大
- 从库在执行大查询、锁表
- 网络延迟
监控延迟的命令:
SHOW SLAVE STATUS\G
-- 查看 Seconds_Behind_Master 字段(单位秒)
解决方法:
- 升级从库硬件
- 减少大事务,拆分批量操作
- 并行复制(MySQL 5.7+ 可配置)
- 对延迟不敏感的业务读从库,敏感业务读主库
七、新手避坑指南
💣 陷阱一:数据不一致(主从延迟)
- 现象:刚在主库插入一条数据,马上去从库查,查不到。
- 原因:网络延迟、从库机器性能差、大事务阻塞。
- 解决:
- 监控
Seconds_Behind_Master指标。 - 对于强一致性要求的读操作(如支付结果),强制走主库读取(Hint 强制读主)。
- 监控
💣 陷阱二:从库写入导致冲突
- 现象:不小心在从库执行了 UPDATE,导致后续主库的同一条数据更新失败(Duplicate entry)。
- 原因:从库默认是可以写的。
- 解决:在从库配置文件中加上
read-only=1,让从库只读。
💣 陷阱三:GTID 模式切换的坑
- 建议:MySQL 5.7+ 推荐开启 GTID(全局事务标识符)模式,它能让主从切换更简单,数据一致性校验更容易。但在开启前,必须确保主从数据完全一致,否则会报错。
八、总结
今天的内容总结成三句话:
- 主从复制通过binlog实现数据同步,是读写分离和高可用的基础。
- 异步复制性能最高,半同步复制更安全,根据业务选择。
- 延迟是常态,需监控并优化,对延迟敏感的业务读主库。
主从复制是数据库从“单打独斗”走向“团队协作”的里程碑。理解了它,你就真正开始触及数据库架构的底层逻辑了!
👋 我是数据库小学妹一个用设计师思维学数据库的转行人。你在配置主从复制时遇到过什么奇葩报错?或者对读写分离有什么疑问?欢迎分享,一起排雷!
本文示例基于 MySQL 8.0。主从复制配置因版本和环境不同略有差异,建议参考官方文档。