MySQL主从复制及进阶配置

一、MySQL主从复制基础

1.1 核心原理与架构

主从复制通过二进制日志(binlog)实现数据同步,核心依赖三个线程和两类日志:

主库binlog dump线程(发送 binlog 事件)

从库IO线程(接收 binlog 并写入中继日志 relay log)、SQL线程(执行中继日志事件)

关键日志:主库的 binlog(记录所有变更)、从库的 relay log(暂存主库 binlog)

同步流程:

1.从库执行CHANGE REPLICATION SOURCE TO配置主库信息及同步起点

2.从库 IO 线程与主库 binlog dump 线程建立连接

3.主库推送 binlog 事件至从库,从库写入 relay log

4.从库 SQL 线程解析 relay log 并重演操作

1.2 基础配置步骤

环境准备

|----|-----------------|-----------|
| | IP地址 | server-id |
| 主库 | 192.168.168.200 | 200 |
| 从库 | 192.168.168.129 | 129 |

主库配置

1.启用binlog并配置唯一标识:

修改/etc/my.cnf:

bash 复制代码
[mysqld]
server_id=200                  # 唯一标识,不可与从库重复
log_bin=/data/mysql/binlog     # binlog存储路径
binlog_format=ROW              # 推荐行级复制,避免语句级复制的兼容性问题
expire_logs_days=7             # binlog自动保留7天

重启主库:

bash 复制代码
systemctl restart mysqld

2.创建复制专用用户

登录主库MySQL,创建具有复制权限的用户:

sql 复制代码
-- 创建用户(允许从库IP访问)
CREATE USER 'repl_user'@'192.168.168.129' IDENTIFIED BY 'Repl@123';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.168.129';
-- 刷新权限
FLUSH PRIVILEGES;

3.获取主库同步起点

锁表防止数据写入,记录binlog文件名和位置:

bash 复制代码
-- 锁表(只读,不影响查询)
FLUSH TABLES WITH READ LOCK;
-- 查看主库状态(记录File和Position)
SHOW MASTER STATUS;

输出示例:

bash 复制代码
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| binlog.000001 |      156 |              |                  |
+---------------+----------+--------------+------------------+

解锁表:

sql 复制代码
UNLOCK TABLES;

从库配置:

1.配置从库唯一标识:

修改/etc/my.cnf:

sql 复制代码
[mysqld]
server_id=129                  # 唯一标识,与主库不同
relay_log=/data/mysql/relaylog # 中继日志路径
read_only=ON                   # 从库只读(仅对非SUPER用户生效)

重启从库:

bash 复制代码
systemctl restart mysqld

2.配置主从连接信息

登录从库MySQL,设置主库地址、用户及同步起点:

sql 复制代码
-- 配置主库信息(替换为实际值)
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='192.168.168.200',
SOURCE_USER='repl_user',
SOURCE_PASSWORD='Repl@123',
SOURCE_LOG_FILE='binlog.000001',  # 主库SHOW MASTER STATUS中的File
SOURCE_LOG_POS=156;               # 主库SHOW MASTER STATUS中的Position

3.启动同步并验证

sql 复制代码
-- 启动从库同步线程
START REPLICA;

-- 查看同步状态(关键参数:Replica_IO_Running和Replica_SQL_Running需为Yes)
SHOW REPLICA STATUS\G

关键输出验证:

sql 复制代码
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Master: 0  # 0表示无延迟

基础功能验证

1.主库创建测试数据:

sql 复制代码
CREATE DATABASE test_repl;
USE test_repl;
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
INSERT INTO t1 (name) VALUES ('repl_test');

2.从库验证同步结果:

sql 复制代码
SHOW DATABASES LIKE 'test_repl';
USE test_repl;
SELECT * FROM t1;  # 应显示主库插入的数据

二、主从复制进阶配置

2.1 延时同步(数据容灾)

通过设置从库延迟同步主库数据,可应对误操作(如误删库表),提供数据恢复窗口。

配置步骤

1.从库设置延迟(单位:秒):

sql 复制代码
-- 停止同步
STOP REPLICA;
-- 设置延迟300秒(5分钟)
CHANGE REPLICATION SOURCE TO SOURCE_DELAY = 300;
-- 重启同步
START REPLICA;

2.验证延迟配置:

sql 复制代码
SHOW REPLICA STATUS\G
-- 查看SQL_Delay参数,应显示300

误操作回复流程

假设主库误删除test_repl库,从库尚未同步该操作:

1.立即停止从库 SQL 线程(防止继续同步误操作):

sql 复制代码
STOP REPLICA SQL_THREAD;

2.定位误操作在 relay log 中的位置:

sql 复制代码
-- 查看当前relay log文件
SHOW REPLICA STATUS\G  # 记录Relay_Log_File值,如relaylog.000002

-- 解析relay log,查找删除操作的位置
SHOW RELAYLOG EVENTS IN 'relaylog.000002';

3.恢复误删除数据:

bash 复制代码
-- 导出误操作前的relay log内容
mysqlbinlog --start-position=4 --stop-position=999 /data/mysql/relaylog.000002 > /tmp/recover.sql

-- 导入恢复数据
mysql -uroot -p < /tmp/recover.sql

4.重置从库(如需脱离主从关系):

sql 复制代码
STOP REPLICA;
RESET REPLICA ALL;  # 清除主库信息

2.2 GTID复制(全局事务ID)

GTID(全局事务 ID)通过唯一标识每个事务,简化主从同步的位置管理,支持自动定位同步起点。

GTID 格式与原理

格式:server_uuid:transaction_id(如a235ccb1-732b-11f0-971f-000c29d6adc7:1-5

原理:主库提交事务时生成 GTID,从库通过 GTID 判断是否已执行该事务,避免重复执行。

配置步骤(在线切换)

1.主从库启用 GTID 一致性检查:

bash 复制代码
-- 先警告模式(检查兼容性)
SET GLOBAL enforce_gtid_consistency = WARN;
-- 无警告后启用严格检查
SET GLOBAL enforce_gtid_consistency = ON;

2.逐步切换 GTID 模式(主从库均执行):

bash 复制代码
-- 从OFF -> OFF_PERMISSIVE(允许匿名事务)
SET GLOBAL gtid_mode = OFF_PERMISSIVE;
-- 再到ON_PERMISSIVE(允许GTID和匿名事务)
SET GLOBAL gtid_mode = ON_PERMISSIVE;
-- 等待所有匿名事务完成(值为0时继续)
SHOW STATUS LIKE 'ongoing_anonymous_transaction_count';
-- 最终启用GTID模式
SET GLOBAL gtid_mode = ON;

3.从库切换为 GTID 同步:

bash 复制代码
-- 停止同步
STOP REPLICA;
-- 启用自动定位(基于GTID)
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 1;
-- 重启同步
START REPLICA;

4.验证 GTID 配置:

sql 复制代码
-- 主库查看已执行的GTID
SELECT @@GLOBAL.gtid_executed;

-- 从库查看同步状态(确认Retrieved_Gtid_Set和Executed_Gtid_Set非空)
SHOW REPLICA STATUS\G

2.3 半同步复制(数据可靠性增强)

半同步复制确保主库提交事务前,至少有一个从库已接收并写入 relay log,避免异步复制的数据丢失风险。

配置步骤

1.主库配置:

sql 复制代码
-- 安装半同步插件
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
-- 启用半同步
SET GLOBAL rpl_semi_sync_source_enabled = 1;
-- 设置超时时间(3秒,超时后降级为异步)
SET GLOBAL rpl_semi_sync_source_timeout = 3000;

2.从库配置:

sql 复制代码
-- 安装半同步插件
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
-- 启用半同步
SET GLOBAL rpl_semi_sync_replica_enabled = 1;
-- 重启IO线程
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;

3.验证半同步状态:

sql 复制代码
-- 主库查看状态(Rpl_semi_sync_source_status应为ON)
SHOW STATUS LIKE 'Rpl_semi_sync_source%';

-- 从库查看状态(Rpl_semi_sync_replica_status应为ON)
SHOW STATUS LIKE 'Rpl_semi_sync_replica%';

功能测试:

1.主库插入数据,观察响应时间(正常应立即返回):

sql 复制代码
INSERT INTO test_repl.t1 (name) VALUES ('semi_sync_test');

2.模拟从库故障(停止从库半同步):

bash 复制代码
-- 从库执行
SET GLOBAL rpl_semi_sync_replica_enabled = 0;
STOP REPLICA IO_THREAD;

3.主库再次插入数据,应等待 3 秒后超时(降级为异步):

sql 复制代码
INSERT INTO test_repl.t1 (name) VALUES ('timeout_test');
-- 输出应显示 Query OK, 1 row affected (3.00 sec)

4.恢复从库半同步:

sql 复制代码
-- 从库执行
SET GLOBAL rpl_semi_sync_replica_enabled = 1;
START REPLICA IO_THREAD;

三、主从复制监控与维护

3.1 关键监控指标

1.主库监控:

sql 复制代码
-- 查看从库连接数
SHOW REPLICAS;
-- 查看binlog状态
SHOW MASTER STATUS;

2.从库监控:

sql 复制代码
-- 同步延迟(Seconds_Behind_Master)
SHOW REPLICA STATUS\G
-- 中继日志应用状态
SHOW GLOBAL STATUS LIKE 'Slave_sql_running_state';

3.2常见问题处理

1.同步延迟:

原因:从库 SQL 线程执行慢、网络延迟。

解决:优化从库性能、增大innodb_buffer_pool_size、避免大事务。

2.线程异常(IO/SQL线程为no):

查看错误日志:cat /data/mysql/[hostname].err

常见原因:网络不通、主库 binlog 文件丢失、权限错误。

总结

主从复制通过基础配置可实现数据同步,进阶功能(延时同步、GTID、半同步)分别解决了数据容灾、同步管理复杂度、数据可靠性问题。生产环境中建议结合 GTID 和半同步复制,同时做好监控与定期备份,确保集群稳定运行。

相关推荐
博一波3 小时前
MySQL 核心文件解析:从配置到存储的 “说明书 + 记录仪” 系统
数据库·mysql
TimberWill3 小时前
idea、服务器、数据库环境时区不一致问题
服务器·数据库·intellij-idea
叫我阿柒啊3 小时前
从Java全栈到前端框架的实战之路
java·数据库·微服务·typescript·前端框架·vue3·springboot
蒋星熠3 小时前
WebSocket网络编程深度实践:从协议原理到生产级应用
网络·数据库·redis·python·websocket·网络协议·微服务
时序数据说4 小时前
物联网时序数据管理的利器:为何IoTDB备受青睐?
大数据·数据库·物联网·时序数据库·iotdb
十八旬5 小时前
苍穹外卖项目实战(day7-2)-购物车操作功能完善-记录实战教程、问题的解决方法以及完整代码
java·开发语言·windows·spring boot·mysql
Java水解5 小时前
MySQL UPDATE 语句:数据更新操作详解
后端·mysql
GBASE5 小时前
GBASE南大通用技术分享:GBase 8a集群内存管理之堆内存
数据库