js.
├── docker-compose.yml # 下面会写这个文件
├── master/
│ ├── data/ # 主库数据持久化目录(自动生成)
│ └── init/
│ └── init-master.sql # 主库初始化脚本
└── slave/
├── data/ # 从库数据持久化目录(自动生成)
└── init/
└── init-slave.sh # 从库自动配置脚本
jsmkdir -p master/data master/init slave/data slave/init
jsversion: '3.8'
services:
# 主库 (Master)
mysql-master:
image: mysql:8.0
container_name: mysql-master
environment:
MYSQL_ROOT_PASSWORD: root123 # 请自行修改密码
command: >
--server-id=1
--log-bin=mysql-bin
--binlog-format=ROW
--default-authentication-plugin=mysql_native_password
volumes:
- ./master/data:/var/lib/mysql # 数据持久化
- ./master/init:/docker-entrypoint-initdb.d # 初始化脚本挂载
ports:
- "3306:3306"
networks:
- mysql-repl-net
healthcheck:
# 健康检查:确保主库完全启动后再启动从库
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot123"]
interval: 5s
timeout: 10s
retries: 5
# 从库 (Slave)
mysql-slave:
image: mysql:8.0
container_name: mysql-slave
environment:
MYSQL_ROOT_PASSWORD: root123 # 请自行修改密码
command: >
--server-id=2
--relay-log=relay-bin
--read-only=1
--default-authentication-plugin=mysql_native_password
volumes:
- ./slave/data:/var/lib/mysql # 数据持久化
- ./slave/init:/docker-entrypoint-initdb.d # 初始化脚本挂载
ports:
- "3307:3306"
networks:
- mysql-repl-net
depends_on:
mysql-master:
condition: service_healthy # 等待主库健康检查通过
# 自定义网络,保证主从通信稳定
networks:
mysql-repl-net:
driver: bridge
在 master/init/ 目录下创建 init-master.sql
js-- 创建用于主从复制的专用用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl123';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
在 slave/init/ 目录下创建 init-slave.sh: (这个脚本会自动去主库拿 Binlog 位置,无需手动操作)
js#!/bin/bash
set -e
# 1. 等待主库完全就绪
echo ">>>> 正在等待主库 MySQL 启动..."
until mysql -h mysql-master -uroot -proot123 -e "SELECT 1" &> /dev/null; do
sleep 2
done
# 2. 动态获取主库的 Binlog 文件名和位置
echo ">>>> 正在获取主库状态..."
MASTER_STATUS=$(mysql -h mysql-master -uroot -proot123 -e "SHOW MASTER STATUS\G")
MASTER_LOG_FILE=$(echo "$MASTER_STATUS" | grep "File:" | awk '{print $2}')
MASTER_LOG_POS=$(echo "$MASTER_STATUS" | grep "Position:" | awk '{print $2}')
echo ">>>> 检测到主库日志: File=$MASTER_LOG_FILE, Position=$MASTER_LOG_POS"
# 3. 配置从库连接
mysql -uroot -proot123 <<-EOSQL
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl123',
MASTER_LOG_FILE='$MASTER_LOG_FILE',
MASTER_LOG_POS=$MASTER_LOG_POS;
START SLAVE;
EOSQL
echo ">>>> 恭喜!主从复制配置自动完成!"
jsdocker-compose up -d
查看日志确认成功:
jsdocker-compose logs -f mysql-slave

验证同步状态:
进入从库数据库检查:
查看 Slave_IO_Running 和 Slave_SQL_Running 是否均为 Yes。
jsdocker exec -it mysql-slave mysql -uroot -proot123 -e "SHOW SLAVE STATUS\G"

在主库写入测试数据
进入主库:
jsdocker exec -it mysql-master mysql -uroot -proot123
在 MySQL 命令行中依次执行:
js-- 1. 创建测试库
CREATE DATABASE test_repl_db;
-- 2. 使用该库
USE test_repl_db;
-- 3. 创建一张表
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
-- 4. 插入一条数据
INSERT INTO users (name) VALUES ('张三');
-- 5. 查看主库数据
SELECT * FROM users;
-- 6. 退出 MySQL
exit;
在从库验证数据同步
jsdocker exec -it mysql-slave mysql -uroot -proot123
请勿用root用户进行插入操作。
js-- 1. 查看是否有这个库(应该能看到 test_repl_db)
SHOW DATABASES;
-- 2. 使用该库
USE test_repl_db;
-- 3. 查看数据(应该能看到 '张三' 这条记录)
SELECT * FROM users;
第一步:在主库锁表并全量备份 这一步的目的是防止备份期间主库又有新数据写入,保证备份是一个一致性的快照。
js# 进入主库容器 docker exec -it mysql-master mysql -uroot -proot123
js-- 全局锁表(此时主库只能读,不能写)
FLUSH TABLES WITH READ LOCK;
-- 【关键】查看并记录主库当前的 Binlog 位置(一会儿要用)
SHOW MASTER STATUS;

注意: 执行完 FLUSH TABLES WITH READ LOCK; 后,千万不要退出这个 MySQL 终端,一退出锁就释放了。把这个窗口放一边,去开一个新的终端。 记录下 SHOW MASTER STATUS 的输出,例如:
js# 在主库执行全量备份,导出所有数据到本地的 backup.sql
docker exec mysql-master mysqldump -uroot -proot123 --single-transaction --all-databases --master-data=2 > backup.sql
js-- 解锁
UNLOCK TABLES;
-- 退出
exit;
js# 1. 停止从库的同步线程
docker exec -it mysql-slave mysql -uroot -proot123 -e "STOP SLAVE; RESET SLAVE ALL;"
# 2. 将备份文件拷贝到从库容器内
docker cp backup.sql mysql-slave:/tmp/
# 3. 导入数据(这步可能需要几秒钟,取决于数据量)
docker exec -i mysql-slave mysql -uroot -proot123 < backup.sql
这里需要用到第一步记录的 Binlog 位置(File 和 Position)。
jsdocker exec -it mysql-slave mysql -uroot -proot123
js-- 配置同步点(我已经帮你填好 File 和 Position 了)
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='repl',
MASTER_PASSWORD='repl123',
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=801;
-- 启动同步
START SLAVE;
-- 检查状态
SHOW SLAVE STATUS\G
看到 Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 就成功了!
本文作者:松轩(^U^)
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!