编辑
2026-04-20
Mysql数据库
00

目录

一、Docker部署MySQL主从复制
1. 创建所有目录
2. 编写 docker-compose.yml
3. 编写主库初始化脚本
4.编写从库自动配置脚本
5. 启动与验证
二、假如从库跟主库数据不一致,怎么把从库恢复跟主库一致
1. 打开终端 A(用于锁表,保持窗口不要关):
2. 打开终端 B(用于备份数据):
3. 回到终端 A,解锁主库:
4.把备份导入从库并重置同步
5.在从库重新配置同步点:

一、Docker部署MySQL主从复制

js
. ├── docker-compose.yml # 下面会写这个文件 ├── master/ │ ├── data/ # 主库数据持久化目录(自动生成) │ └── init/ │ └── init-master.sql # 主库初始化脚本 └── slave/ ├── data/ # 从库数据持久化目录(自动生成) └── init/ └── init-slave.sh # 从库自动配置脚本

1. 创建所有目录

js
mkdir -p master/data master/init slave/data slave/init

2. 编写 docker-compose.yml

js
version: '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

3. 编写主库初始化脚本

在 master/init/ 目录下创建 init-master.sql

js
-- 创建用于主从复制的专用用户 CREATE USER 'repl'@'%' IDENTIFIED BY 'repl123'; -- 授予复制权限 GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;

4.编写从库自动配置脚本

在 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 ">>>> 恭喜!主从复制配置自动完成!"

5. 启动与验证

js
docker-compose up -d

查看日志确认成功:

js
docker-compose logs -f mysql-slave

image.png

验证同步状态:

进入从库数据库检查:

查看 Slave_IO_Running 和 Slave_SQL_Running 是否均为 Yes。

js
docker exec -it mysql-slave mysql -uroot -proot123 -e "SHOW SLAVE STATUS\G"

image.png

在主库写入测试数据

进入主库:

js
docker 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;

在从库验证数据同步

js
docker exec -it mysql-slave mysql -uroot -proot123

请勿用root用户进行插入操作。

js
-- 1. 查看是否有这个库(应该能看到 test_repl_db) SHOW DATABASES; -- 2. 使用该库 USE test_repl_db; -- 3. 查看数据(应该能看到 '张三' 这条记录) SELECT * FROM users;

二、假如从库跟主库数据不一致,怎么把从库恢复跟主库一致

第一步:在主库锁表并全量备份 这一步的目的是防止备份期间主库又有新数据写入,保证备份是一个一致性的快照。

1. 打开终端 A(用于锁表,保持窗口不要关):

js
# 进入主库容器 docker exec -it mysql-master mysql -uroot -proot123
js
-- 全局锁表(此时主库只能读,不能写) FLUSH TABLES WITH READ LOCK; -- 【关键】查看并记录主库当前的 Binlog 位置(一会儿要用) SHOW MASTER STATUS;

image.png

注意: 执行完 FLUSH TABLES WITH READ LOCK; 后,千万不要退出这个 MySQL 终端,一退出锁就释放了。把这个窗口放一边,去开一个新的终端。 记录下 SHOW MASTER STATUS 的输出,例如:

2. 打开终端 B(用于备份数据):

js
# 在主库执行全量备份,导出所有数据到本地的 backup.sql docker exec mysql-master mysqldump -uroot -proot123 --single-transaction --all-databases --master-data=2 > backup.sql

3. 回到终端 A,解锁主库:

js
-- 解锁 UNLOCK TABLES; -- 退出 exit;

4.把备份导入从库并重置同步

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

5.在从库重新配置同步点:

这里需要用到第一步记录的 Binlog 位置(File 和 Position)。

js
docker exec -it mysql-slave mysql -uroot -proot123
js
-- 配置同步点(我已经帮你填好 FilePosition 了) 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 许可协议。转载请注明出处!