一、什么是主从复制?
主从复制是指将主数据库的数据同步到一个或多个从数据库,实现数据备份、负载均衡、高可用等功能。
1.1 主从复制原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ┌─────────────────────────────────────────────────────────────────┐ │ 主从复制原理 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 主库(Master) │ │ ┌─────────┐ │ │ │ 写入 │ │ │ └────┬────┘ │ │ │ │ │ ┌──────┴──────┐ │ │ │ Binary Log │ │ │ └──────┬──────┘ │ │ │ │ │ │ 同步 │ │ ▼ │ │ ┌───────────────────────────────────────────┐ │ │ │ IO Thread │ │ │ └───────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────┐ │ │ │ Relay Log(中继日志) │ │ │ └───────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────┐ │ │ │ 从库(Slave)│ │ │ └────────────┘ │ │ ┌─────────┐ │ │ │ SQL执行 │ │ │ └────┬────┘ │ │ │ │ │ ┌─────────┐ │ │ │ 数据 │ │ │ └─────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
|
1.2 主从复制优点
| 优点 |
说明 |
| 数据备份 |
实时备份,防止数据丢失 |
| 读写分离 |
主库写,从库读,分担压力 |
| 负载均衡 |
多从库分散查询压力 |
| 高可用 |
主库故障时可切换从库 |
| 数据分析 |
从库可进行数据分析,不影响主库 |
二、主从复制架构
2.1 一主一从
1 2 3 4 5 6
| ┌─────────────┐ 同步 ┌─────────────┐ │ 主库 │ ───────────────────→ │ 从库 │ │ (Master) │ │ (Slave) │ │ │ │ │ │ 写入/读取 │ │ 读取 │ └─────────────┘ └─────────────┘
|
2.2 一主多从
1 2 3 4 5 6 7 8
| ┌─────────────┐ │ 从库1 │ ┌─────────────┐ ├─────────────┤ ┌─────────────┐ │ 主库 │ ───→│ 从库2 │ ───→│ 从库3 │ │ (Master) │ ├─────────────┤ │ (Slave) │ │ │ │ 从库N │ └─────────────┘ │ 写入/读取 │ └─────────────┘ └─────────────┘
|
2.3 双主复制
1 2 3 4 5
| ┌─────────────┐ 双向同步 ┌─────────────┐ │ 主库A │ ←────────────────→ │ 主库B │ │ │ │ │ │ 写入/读取 │ │ 写入/读取 │ └─────────────┘ └─────────────┘
|
2.4 多主一从
1 2 3 4 5 6 7 8 9
| ┌─────────────┐ │ 主库1 │ ─┐ └─────────────┘ │ ┌─────────────┐ │ ┌─────────────┐ │ 主库2 │ ─┼────→│ 从库 │ └─────────────┘ │ │ (Slave) │ ┌─────────────┐ │ └─────────────┘ │ 主库N │ ─┘ └─────────────┘
|
三、主从复制配置
3.1 环境说明
| 角色 |
IP |
端口 |
| Master |
192.168.1.100 |
3306 |
| Slave |
192.168.1.101 |
3306 |
3.2 Master配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin
binlog_do_db = mydb
binlog_ignore_db = mysql
binlog_format = ROW
gtid_mode = ON enforce_gtid_consistency = ON
sudo systemctl restart mysql
|
3.3 创建复制用户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
|
3.4 Slave配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
server-id = 2
relay_log = /var/log/mysql/mysql-relay-bin
gtid_mode = ON enforce_gtid_consistency = ON
read_only = ON super_read_only = ON
sudo systemctl restart mysql
|
3.5 启动复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
CHANGE MASTER TO MASTER_HOST='192.168.1.100', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=1234;
CHANGE MASTER TO MASTER_HOST='192.168.1.100', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_AUTO_POSITION=1;
START SLAVE;
SHOW SLAVE STATUS\G
STOP SLAVE;
RESET SLAVE ALL;
|
四、复制原理详解
4.1 复制过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ┌─────────────────────────────────────────────────────────────────┐ │ 完整复制流程 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. Master执行SQL,写入数据 │ │ ↓ │ │ 2. 记录Binary Log(记录位置:1234) │ │ ↓ │ │ 3. Slave IO Thread连接Master │ │ ↓ │ │ 4. Master发送Binary Log给Slave │ │ ↓ │ │ 5. Slave写入Relay Log │ │ ↓ │ │ 6. Slave SQL Thread读取Relay Log │ │ ↓ │ │ 7. 执行SQL,完成数据同步 │ │ │ └─────────────────────────────────────────────────────────────────┘
|
4.2 复制类型
| 类型 |
说明 |
优点 |
缺点 |
| 异步复制 |
Master不等待Slave完成 |
性能好 |
可能丢失数据 |
| 半同步复制 |
Master等待至少一个Slave |
数据安全 |
有延迟 |
| 全同步复制 |
Master等待所有Slave |
数据最安全 |
性能差 |
4.3 配置半同步复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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 = 1000; # 毫秒
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
|
五、读写分离
5.1 读写分离原理
1 2 3 4 5 6 7 8 9 10
| ┌─────────────┐ │ 客户端 │ └──────┬──────┘ │ ├──────────────────┬──────────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 主库 │ │ 从库1 │ │ 从库2 │ │ (写入) │ │ (读取) │ │ (读取) │ └─────────────┘ └─────────────┘ └─────────────┘
|
5.2 实现方式
5.3 示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import pymysql
master_conn = pymysql.connect( host='192.168.1.100', port=3306, user='app_user', password='password', database='mydb' )
slave_conn = pymysql.connect( host='192.168.1.101', port=3306, user='app_user', password='password', database='mydb' )
def write_data(sql, params): with master_conn.cursor() as cursor: cursor.execute(sql, params) master_conn.commit()
def read_data(sql, params=None): with slave_conn.cursor() as cursor: cursor.execute(sql, params or []) return cursor.fetchall()
|
六、延迟复制
6.1 延迟复制配置
1 2 3 4 5 6
| CHANGE MASTER TO MASTER_DELAY = 3600; # 延迟1小时
SHOW SLAVE STATUS\G
|
6.2 使用场景
| 场景 |
说明 |
| 误操作恢复 |
延迟复制,可从从库恢复误删数据 |
| 备份 |
从延迟从库备份,不影响主库 |
| 测试 |
在从库测试,不影响业务 |
七、GTID复制
7.1 什么是GTID?
GTID(Global Transaction ID)是全局事务ID,每个事务有一个唯一标识。
1 2
| 格式:UUID:事务编号 示例:a1b2c3d4-e5f6-7890-abcd-ef1234567890:1
|
7.2 GTID优势
| 优势 |
说明 |
| 自动定位 |
不需要指定binlog文件和位置 |
| 故障恢复 |
更容易确定同步位置 |
| 一致性 |
保证事务不重复执行 |
7.3 GTID配置
1 2 3 4
| [mysqld]
gtid_mode = ON enforce_gtid_consistency = ON
|
7.4 GTID运维
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| SHOW MASTER STATUS\G SHOW SLAVE STATUS\G
SET GTID_NEXT='a1b2c3d4-e5f6-7890-abcd-ef1234567890:1'; BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC';
RESET SLAVE ALL;
CHANGE MASTER TO MASTER_HOST='192.168.1.100', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_AUTO_POSITION=1;
|
八、故障处理
8.1 常见错误
8.2 数据同步
1 2 3 4 5 6 7 8 9
|
mysqldump -uroot -p
mysql -uroot -p < backup.sql
|
8.3 主库故障切换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
SHOW SLAVE STATUS\G
STOP SLAVE; RESET MASTER;
CHANGE MASTER TO MASTER_HOST='192.168.1.101', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_AUTO_POSITION=1;
|
九、监控与维护
9.1 监控指标
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SHOW SLAVE STATUS\G
SHOW MASTER STATUS\G
SHOW PROCESSLIST;
|
9.2 常用命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| START SLAVE;
STOP SLAVE;
RESET SLAVE;
SHOW SLAVE HOSTS;
SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;
|
十、实战案例
10.1 Docker搭建主从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| docker run -d \ --name mysql-master \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123 \ -v ~/mysql/master:/var/lib/mysql \ -e server-id=1 \ -e log-bin=mysql-bin \ mysql:8
docker run -d \ --name mysql-slave \ -p 3307:3306 \ -e MYSQL_ROOT_PASSWORD=root123 \ -v ~/mysql/slave:/var/lib/mysql \ -e server-id=2 \ -e relay-log=mysql-relay-bin \ mysql:8
|
10.2 配置多主一从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
CHANGE MASTER TO MASTER_HOST='192.168.1.100', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_AUTO_POSITION=1, GET_MASTER_PUBLIC_KEY=1 FOR CHANNEL 'master-1';
CHANGE MASTER TO MASTER_HOST='192.168.1.101', MASTER_USER='repl', MASTER_PASSWORD='repl_password', MASTER_AUTO_POSITION=1, GET_MASTER_PUBLIC_KEY=1 FOR CHANNEL 'master-2';
START SLAVE FOR CHANNEL 'master-1'; START SLAVE FOR CHANNEL 'master-2';
|
十一、常见问题
11.1 延迟太高
1 2 3 4 5 6 7 8 9 10 11 12
|
SET GLOBAL slave_parallel_workers = 4;
|
11.2 数据不一致
参考资料
持续更新中…欢迎收藏!
#MySQL #主从复制 #读写分离 #GTID #高可用 #教程