🧙♂️ MySQL主从复制部署完整指南
📋 前置准备
# 创建数据目录(在主节点和从节点都要执行)
sudo mkdir -p /mnt/sdc/mysql8/master/data /mnt/sdc/mysql8/master/conf
sudo mkdir -p /mnt/sdc/mysql8/slave/data /mnt/sdc/mysql8/slave/conf
# 设置目录权限
sudo chmod -R 755 /mnt/sdc/mysql8/
📝 第一步:创建主库配置文件
主库配置 /mnt/sdc/mysql8/master/conf/my.cnf
:
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW
gtid_mode = ON
enforce_gtid_consistency = ON
# 需要同步的数据库(可选)
# binlog-do-db = testdb
# 忽略同步的数据库
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
[mysql]
default-character-set = utf8mb4
📝 第二步:创建从库配置文件
从库配置 /mnt/sdc/mysql8/slave/conf/my.cnf
:
[mysqld]
server-id = 2
relay-log = mysql-relay-bin
read_only = ON
super_read_only = ON
gtid_mode = ON
enforce_gtid_consistency = ON
[mysql]
default-character-set = utf8mb4
🐳 第三步:创建Docker Stack部署文件
mysql-stack.yml:
# Docker Compose 文件版本 (兼容 Swarm 模式)
version: "3.8"
services:
# 主数据库服务定义
mysql-master:
# 使用 MySQL 8.2 官方镜像 (实际使用时建议确认版本可用性)
image: mysql:8.2
# Swarm 部署配置
deploy:
replicas: 1 # 主库单实例运行
placement:
constraints:
- node.hostname==uubuntu # 明确指定在manager节点运行
restart_policy: # 重启策略配置
condition: on-failure # 仅在失败时重启
delay: 5s # 重启间隔5秒
max_attempts: 1 # 最多尝试3次
# 网络端口映射 (暴露主库3306端口到宿主机)
ports:
- "3306:3306"
# 数据卷绑定挂载 (将宿主机目录映射到容器内)
volumes:
- type: bind # 日志目录绑定
source: /mnt/sdc/mysql8/master/log
target: /var/log/mysql
- type: bind # 数据目录绑定
source: /mnt/sdc/mysql8/master/data
target: /var/lib/mysql
- type: bind # 初始化脚本目录
source: ./master-init
target: /docker-entrypoint-initdb.d
# 环境变量配置
environment:
MYSQL_ROOT_PASSWORD: "123456" # 设置root密码
MYSQL_ROOT_HOST: "%" # 允许root远程访问 (MySQL 8.x 必需)
# MySQL 服务器启动参数
command:
- --server-id=1 # 唯一服务器ID (主从必须不同)
- --log-bin=mysql-bin # 启用二进制日志
- --binlog-format=ROW # 使用行级日志格式
- --log-slave-updates=ON # 记录从库更新到二进制日志
- --gtid-mode=ON # 启用全局事务ID (GTID)
- --enforce-gtid-consistency=ON # 强制GTID一致性
- --binlog-transaction-dependency-tracking=WRITESET # MySQL 8 复制优化
# 健康检查配置
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p123456"]
interval: 5s # 每5秒检查一次
timeout: 5s # 超时时间5秒
retries: 10 # 连续失败10次判定为不健康
# 从数据库服务定义
mysql-slave:
image: mysql:8.2
deploy:
replicas: 1 # 从库单实例运行
placement:
constraints:
- node.hostname==ubuntumini # 明确指定在worker节点运行
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 1
# 数据卷绑定 (与主库分离的目录)
volumes:
- type: bind
source: /mnt/sdc/mysql8/slave/log
target: /var/log/mysql
- type: bind
source: /mnt/sdc/mysql8/slave/data
target: /var/lib/mysql
- type: bind # 从库初始化脚本目录
source: ./slave-init
target: /docker-entrypoint-initdb.d
# 环境变量 (密码需与主库一致)
environment:
MYSQL_ROOT_PASSWORD: "123456"
MYSQL_ROOT_HOST: "%"
# 从库专用启动参数
command:
- --server-id=2 # 唯一服务器ID (从库必须不同于主库)
- --log-bin=mysql-bin # 启用二进制日志
- --binlog-format=ROW # 使用行级日志格式
- --log-slave-updates=ON # 记录从库更新到二进制日志
- --gtid-mode=ON # 启用全局事务ID (GTID)
- --enforce-gtid-consistency=ON # 强制GTID一致性
- --skip-slave-start # 启动时不自动开始复制
- --read-only=ON # 设置从库为只读模式
- --relay-log=mysql-relay-bin # 启用中继日志
- --relay-log-index=mysql-relay-bin.index # 中继日志索引文件
# 健康检查配置 (用于验证复制配置是否完成)
healthcheck:
# test: [
# "CMD-SHELL",
# "test -f /var/lib/mysql/slave.configured || (mysql -uroot -p123456 -e 'SHOW SLAVE STATUS\\G' | grep -q 'Waiting for master')"
# ]
test: ["CMD", "mysqladmin", "ping", "-uroot", "-p123456"]
interval: 10s
timeout: 5s
retries: 12
# Compose v3 不支持 depends_on 的健康依赖,已移除
# 共享网络配置 (使用预先创建的overlay网络)
networks:
default:
name: backend_network # 新推荐写法(省略 external)
external: true
🚀 第四步:部署MySQL集群
# 部署Stack
docker stack deploy -c mysql-stack.yml mysql
# 查看服务状态
docker service ls
docker service ps mysql_mysql-master
docker service ps mysql_mysql-slave
⚙️ 第五步:配置主库复制用户
# 进入主库容器
docker exec -it mysql-master mysql -uroot -p123456
在主库中执行:
-- 创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
-- 查看主库状态(记录File和Position)
SHOW MASTER STATUS\G
🔗 第六步:配置从库复制
# 进入从库容器
docker exec -it mysql-slave mysql -uroot -p123456
在从库中执行:
-- 配置主从复制
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_AUTO_POSITION = 1;
-- 启动复制
START SLAVE;
-- 查看复制状态
SHOW SLAVE STATUS\G
应看到:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
✅ 第七步:验证主从复制
测试数据同步
# 在主库创建测试数据
docker exec -it mysql-master mysql -uroot -p123456 -e "
CREATE DATABASE IF NOT EXISTS testdb;
USE testdb;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');
"
# 在从库检查数据同步
docker exec -it mysql-slave mysql -uroot -p123456 -e "
USE testdb;
SELECT * FROM users;
SHOW SLAVE STATUS\G
"
🎯 第八步:监控和维护脚本
创建监控脚本 check_replication.sh
#!/bin/bash
echo "🔍 检查MySQL主从复制状态..."
# 检查主库状态
echo "=== 主库状态 ==="
docker exec mysql-master mysql -uroot -p123456 -e "SHOW MASTER STATUS\G"
echo -e "\n=== 从库状态 ==="
docker exec mysql-slave mysql -uroot -p123456 -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_Error"
echo -e "\n=== 测试数据同步 ==="
docker exec mysql-master mysql -uroot -p123456 -e "
USE testdb;
INSERT INTO users (name) VALUES ('Test_' || DATE_FORMAT(NOW(), '%H%i%s'));
SELECT COUNT(*) as total_users FROM users;
"
sleep 2
docker exec mysql-slave mysql -uroot -p123456 -e "
USE testdb;
SELECT COUNT(*) as slave_users FROM users;
"
给脚本执行权限:
chmod +x check_replication.sh
./check_replication.sh
🛠 第九步:一键修复脚本
创建修复脚本 fix_replication.sh
:
#!/bin/bash
echo "🔧 开始修复MySQL主从复制..."
# 停止从库复制
docker exec mysql-slave mysql -uroot -p123456 -e "STOP SLAVE; RESET SLAVE ALL;"
# 重新配置复制
docker exec mysql-slave mysql -uroot -p123456 -e "
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_AUTO_POSITION = 1;
START SLAVE;
"
# 检查修复结果
echo "✅ 修复完成,检查状态:"
docker exec mysql-slave mysql -uroot -p123456 -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running|Last_Error"
📊 第十步:健康检查指标
正常的复制状态应该显示:
-
✅
Slave_IO_Running: Yes
-
✅
Slave_SQL_Running: Yes
-
✅
Seconds_Behind_Master: 0
-
✅
Last_Error:
(空)
如果出现问题:
# 查看详细错误信息 docker exec mysql-slave mysql -uroot -p123456 -e "SHOW SLAVE STATUS\G" | grep Last_Error # 跳过特定错误(谨慎使用) docker exec mysql-slave mysql -uroot -p123456 -e "STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;"
🎩 魔法总结
部署成功的关键步骤:
-
✅ 正确配置主从
my.cnf
文件 -
✅ 创建复制用户并授权
-
✅ 使用GTID自动定位(
MASTER_AUTO_POSITION=1
) -
✅ 验证数据实时同步
(魔法杖挥出绿色成功光芒)✨ 恭喜!你现在已经掌握了MySQL主从复制的完整魔法!
记住定期检查:
# 每天检查一次复制状态
0 2 * * * /path/to/check_replication.sh >> /var/log/mysql_replication.log
现在你的数据库拥有了高可用性和数据备份的超能力!🐋🚀