以下步骤严格区分主服务器(Master,IP:192.168.1.190)和从服务器(Slave,IP:192.168.1.196)操作,包含环境准备、配置修复、网络排查、同步验证全流程,确保每一步可落地。
一、前置环境准备(主、从服务器均执行)
- 安装 Docker 与 MySQL 镜像
bash
# 1. 安装Docker(若未安装)
yum install docker -y
systemctl start docker
systemctl enable docker
# 2. 拉取MySQL 5.7镜像(支持GTID,稳定兼容,如需其他版本需修改标签)
docker pull mysql:5.7 # ← 如需其他版本(如5.7.40),可替换为mysql:5.7.40
# 3. 安装基础工具(后续网络测试、权限操作需用到)
yum install net-tools nc -y
- 清理历史残留(若之前部署过 MySQL 容器)
bash
# 停止并删除所有MySQL容器(避免端口/配置冲突)
docker stop $(docker ps -aq --filter "name=mysql-*") 2>/dev/null
docker rm $(docker ps -aq --filter "name=mysql-*") 2>/dev/null
# 删除旧挂载目录(首次部署可跳过,避免配置残留,路径需与后续一致)
rm -rf /docker/mysql 2>/dev/null # ← 若自定义挂载目录,需同步修改此处路径
二、主服务器(192.168.1.190)操作:配置 GTID 与复制用户
- 创建挂载目录与 GTID 配置文件
bash
# 1. 创建主库数据、配置目录(路径可自定义,需与后续挂载一致)
mkdir -p /docker/mysql/master/data /docker/mysql/master/conf # ← 若修改路径,后续挂载需同步变更
# 2. 编写GTID核心配置文件(my.cnf)
cat > /docker/mysql/master/conf/my.cnf << EOF
[mysqld]
# 基础标识(主从必须唯一,主库设为10,从库需不同)
server-id = 10 # ← 可自定义(如1、100等),但需与从库server-id不同
# 二进制日志(GTID依赖,记录事务,路径可自定义)
log_bin = /var/lib/mysql/mysql-bin # ← 容器内路径,若修改需确保目录可写
log_bin_index = /var/lib/mysql/mysql-bin.index
# GTID关键配置
gtid_mode = ON # 启用GTID模式(固定值,无需修改)
enforce_gtid_consistency = ON # 强制GTID事务一致性(固定值,无需修改)
log_slave_updates = 1 # 允许从库同步的事务写入自身binlog(固定值,无需修改)
# 其他配置
binlog_format = ROW # 推荐ROW模式,避免SQL兼容问题(固定值,无需修改)
expire_logs_days = 7 # binlog保留7天,可根据磁盘空间修改(如30天)
character-set-server = utf8mb4 # 统一字符集(可根据需求修改,如utf8)
collation-server = utf8mb4_unicode_ci
default_storage_engine = InnoDB # 仅支持InnoDB(GTID不支持MyISAM,固定值)
EOF
# 3. 修正配置文件权限(避免MySQL因安全问题忽略配置)
chmod 644 /docker/mysql/master/conf/my.cnf
- 启动主库容器
bash
docker run -d \
--name mysql-master \ # 容器名可自定义(如master-db)
-p 3306:3306 \ # 主机端口:容器端口,若3306被占用,改为主机端口如3307:3306 ← 需修改主机端口(左侧)
-v /docker/mysql/master/conf/my.cnf:/etc/mysql/my.cnf \ # 挂载配置,若目录修改需同步变更
-v /docker/mysql/master/data:/var/lib/mysql \ # 挂载数据(持久化),目录修改需同步变更
-e MYSQL_ROOT_PASSWORD=root123 \ # 主库root密码,需自定义(如StrongPwd@2024)← 需修改为实际密码
--restart=always \ # 开机自启(固定值,无需修改)
mysql:5.7 # 镜像标签需与拉取的版本一致,若修改需同步 ← 需与步骤一拉取的镜像版本一致
- 验证主库配置是否生效
bash
# 1. 进入主库MySQL终端(密码需与启动时的MYSQL_ROOT_PASSWORD一致)
docker exec -it mysql-master mysql -uroot -proot123 # ← 替换为实际root密码
# 2. 检查关键参数(均需返回配置值,而非默认值)
show variables like 'server_id'; # 应返回步骤1中配置的server-id(如10)
show variables like 'gtid_mode'; # 应返回ON
show variables like 'log_bin'; # 应返回ON
show variables like 'enforce_gtid_consistency'; # 应返回ON
- 创建主从复制专用用户
sql
# 在主库MySQL终端执行:创建slave用户并授权
-- mysql5.7以上需分开执行
create user 'slave'@'192.168.1.%' identified by '123456'; # ← 需修改:'slave'为用户名,'192.168.1.%'为从库网段(确保包含从库IP),'123456'为密码
grant replication slave on *.* to 'slave'@'192.168.1.%'; # ← 用户名和网段需与上一行一致
# 刷新权限使配置生效
flush privileges;
# 临时设置主库为只读(避免配置期间写入数据,后续会解除)
set @@global.read_only=ON;
三、从服务器(192.168.1.196)操作:配置 GTID 与网络验证
- 先解决网络连通性(核心前提)
bash
# 1. 测试从库到主库3306端口的连通性(主库端口需与主库容器映射的主机端口一致)
nc -zv 192.168.1.190 3306 # ← 需修改:主库IP(192.168.1.190)和端口(3306,若主库修改需同步)
# 成功结果:Ncat: Connected to 192.168.1.190:3306.
# 2. 若失败(No route to host),排查方向:
# - 主库IP是否正确(主库执行ip addr确认)
# - 主从是否在同一网段(主从均执行ip addr,确保192.168.1.x)
# - 主库防火墙是否拦截(主库执行iptables -A INPUT -p tcp --dport 3306 -j ACCEPT)← 端口需与主库一致
- 创建从库挂载目录与配置文件
bash
# 1. 创建从库数据、配置目录(路径可自定义,需与后续挂载一致)
mkdir -p /docker/mysql/slave/data /docker/mysql/slave/conf # ← 若修改路径,后续挂载需同步变更
# 2. 编写从库GTID配置文件(比主库多2个关键参数)
cat > /docker/mysql/slave/conf/my.cnf << EOF
[mysqld]
# 基础标识(必须与主库不同,从库设为20)
server-id = 20 # ← 可自定义(如2、200等),但需与主库server-id不同
# 中继日志(从库核心,存储主库同步的binlog,路径可自定义)
relay-log = /var/lib/mysql/relaylog # ← 容器内路径,若修改需确保目录可写
relay-log-index = /var/lib/mysql/relaylog.index
# GTID关键配置(与主库一致)
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = 1
log_bin = /var/lib/mysql/mysql-bin # 从库必须开启binlog(GTID要求)
# 从库专属配置
skip-slave-start = 1 # 容器启动时不自动启动同步(固定值,无需修改)
read-only = 1 # 从库默认只读(仅限制普通用户,root仍可写,固定值)
# 其他配置(与主库统一)
binlog_format = ROW
expire_logs_days = 7 # 可根据磁盘空间修改(如30天)
character-set-server = utf8mb4 # 需与主库一致,若主库修改需同步
collation-server = utf8mb4_unicode_ci
default_storage_engine = InnoDB
EOF
# 3. 修正配置文件权限(避免被MySQL忽略)
chmod 644 /docker/mysql/slave/conf/my.cnf
- 启动从库容器
bash
docker run -d \
--name mysql-slave \ # 容器名可自定义(如slave-db)
-p 3306:3306 \ # 若与主库同主机,改为主机端口如3308:3306(避免冲突)← 需修改主机端口(左侧)
-v /docker/mysql/slave/conf/my.cnf:/etc/mysql/my.cnf \ # 挂载配置,目录修改需同步变更
-v /docker/mysql/slave/data:/var/lib/mysql \ # 挂载数据,目录修改需同步变更
-e MYSQL_ROOT_PASSWORD=root123 \ # 与主库root密码一致,需修改为实际密码 ← 需与主库root密码相同
--restart=always \ # 开机自启(固定值,无需修改)
mysql:5.7 # 镜像标签需与主库一致,若修改需同步 ← 需与步骤一拉取的镜像版本一致
- 验证从库配置是否生效
bash
# 1. 进入从库MySQL终端(密码需与启动时的MYSQL_ROOT_PASSWORD一致)
docker exec -it mysql-slave mysql -uroot -proot123 # ← 替换为实际root密码
# 2. 检查关键参数(均需返回配置值)
show variables like 'server_id'; # 应返回步骤2中配置的server-id(如20)
show variables like 'gtid_mode'; # 应返回ON
show variables like 'relay_log'; # 应返回/var/lib/mysql/relaylog(与配置一致)
四、配置 GTID 主从同步(从服务器操作)
- 执行同步命令(核心步骤)
sql
# 在从库MySQL终端执行:
# 1. 临时设置从库为只读(确保配置期间数据一致)
set @@global.read_only=ON;
# 2. 停止并重置同步状态(清空旧配置,首次部署也需执行)
stop slave;
reset slave;
# 3. 配置GTID同步(替换为主库实际信息)
change master to
master_host='192.168.1.190', # 主库IP,需修改为实际主库IP ← 需修改为实际主库IP
master_user='slave', # 主库创建的复制用户,需与主库一致 ← 需与主库创建的用户名一致
master_password='123456', # 复制用户密码,需与主库一致 ← 需与主库设置的密码一致
master_port=3306, # 主库端口,需与主库容器映射的主机端口一致 ← 需修改为主库实际端口
master_auto_position=1; # GTID关键:自动定位同步位置(固定值,无需修改)
# 4. 启动从库同步进程
start slave;
- 验证同步状态(成功的核心标志)
sql
# 在从库MySQL终端执行(竖版显示,便于查看)
show slave status\G
# 重点检查以下2项,必须均为Yes:
# 1. Slave_IO_Running: Yes → IO线程正常(能从主库拉取binlog)
# 2. Slave_SQL_Running: Yes → SQL线程正常(能执行拉取的事务)
# 其他关键参数(辅助验证):
# - Retrieved_Gtid_Set: 非空 → 已拉取主库的GTID事务
# - Executed_Gtid_Set: 与Retrieved_Gtid_Set一致 → 已执行所有拉取的事务
五、解除只读与功能测试(主、从配合操作)
- 主库解除只读(主服务器操作)
bash
# 进入主库MySQL终端(密码需与主库root密码一致)
docker exec -it mysql-master mysql -uroot -proot123 # ← 替换为实际root密码
# 解除只读(允许业务写入数据)
set @@global.read_only=OFF;
- 测试数据同步(验证 GTID 生效)① 主库写入测试数据(主服务器操作)
sql
# 主库MySQL终端执行:
# 创建测试库(库名可自定义)
create database gtid_test; # ← 库名可自定义(如test_db)
use gtid_test;
# 创建测试表并插入数据(表结构和数据可自定义)
create table user(id int, name varchar(20)); # ← 表名和字段可自定义
insert into user values(1, 'gtid_sync_test'); # ← 数据可自定义
② 从库验证同步结果(从服务器操作)
sql
# 从库MySQL终端执行:
# 查看是否同步到测试库(库名需与主库一致)
show databases like 'gtid_test'; # ← 需与主库创建的库名一致
# 查看测试表数据(若能看到主库插入的数据,同步成功)
use gtid_test; # ← 需与主库库名一致
select * from user; # ← 需与主库表名一致,应返回主库插入的数据
六、常见问题与解决方案
| 问题现象 | 排查方向 | 解决步骤 | 执行服务器 |
|---|---|---|---|
| 配置文件被忽略(World-writable 警告) | 配置文件权限过高(777) | chmod 644 /docker/mysql/xxx/conf/my.cnf(路径需与实际一致)← 需修改为实际配置文件路径 | 主 / 从(对应服务器) |
| Slave_IO_Running: Connecting | 网络不通或复制用户错误 | 1. nc -zv 主库IP 3306 验证网络(IP 和端口需实际值)← 需修改为主库实际 IP 和端口2. 主库重新授权:grant replication slave on *.* to 'slave'@'192.168.1.%' identified by '123456';(用户名、网段、密码需实际值)← 需修改为实际信息 | 从库(网络测试)、主库(授权) |
| Slave_SQL_Running: No | 主从数据不一致 | 1. 从库删除冲突表:drop table 冲突表名;(表名需实际值)← 需修改为冲突表名2. 重启同步:stop slave; start slave; | 从服务器 |
| 主库 show master status 空 | binlog 未开启 | 检查主库 my.cnf 是否有 log_bin=mysql-bin,重启主库容器:docker restart mysql-master(容器名需实际值)← 需修改为实际容器名 | 主服务器 |
七、最终确认清单
- 主库:
gtid_mode=ON、log_bin=ON、server_id=10(需与配置一致)→ 主服务器 - 从库:
gtid_mode=ON、relay_log配置正确、server_id=20(需与配置一致)→ 从服务器 - 网络:从库
nc -zv 主库IP 3306成功(IP 和端口需实际值)→ 从服务器 - 同步状态:从库
Slave_IO_Running=Yes且Slave_SQL_Running=Yes→ 从服务器 - 数据测试:主库写入数据,从库能同步 → 主、从服务器
完成以上步骤,基于 GTID 的 MySQL 主从复制架构即部署完成,后续可支持主库写入、从库只读查询,且切换主从时无需手动定位 binlog 文件和 pos 位置。
1841

被折叠的 条评论
为什么被折叠?



