ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Docker部署MySQL主从复制的实战指南与避坑技巧

Docker部署MySQL主从复制的实战指南与避坑技巧

1. 项目概述

MySQL主从复制是企业级数据库架构中的基础配置方案,而Docker容器化部署正逐渐成为现代运维的标准实践。将两者结合既能发挥容器化的快速部署优势,又能实现传统数据库的高可用特性。我在最近的生产环境迁移项目中,完整实践了基于Docker的MySQL 8主从复制方案,过程中踩遍了几乎所有可能的坑——从网络配置冲突到GTID同步异常,从权限设置错误到字符集不匹配。本文将呈现经过实战检验的完整配置流程,包含那些官方文档不会告诉你的细节陷阱。

2. 环境准备与拓扑设计

2.1 容器网络规划

主从复制对网络延迟敏感,推荐使用自定义bridge网络而非默认的docker0网络。以下创建专用网络的命令包含MTU优化参数:

docker network create \ --driver bridge \ --subnet=172.28.0.0/16 \ --gateway=172.28.5.1 \ --opt "com.docker.network.bridge.mtu=1500" \ mysql-replication-net

注意:MTU值需要与宿主机的物理网卡保持一致(通过ifconfig查看),容器间巨型帧传输失败是常见同步中断原因。

2.2 存储卷配置

数据持久化必须使用volume而非bind mount,避免权限问题:

docker volume create mysql-master-data docker volume create mysql-slave-data

验证volume路径是否符合MySQL的datadir要求:

docker run --rm -v mysql-master-data:/var/lib/mysql alpine \ ls -ld /var/lib/mysql

3. 主库配置实战

3.1 主库容器启动

使用官方mysql:8.0镜像启动主库,关键参数包括server-id和log-bin:

docker run -d --name mysql-master \ --network mysql-replication-net \ --ip 172.28.5.10 \ -v mysql-master-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=Master@123 \ -e MYSQL_ROOT_HOST='%' \ mysql:8.0 \ --server-id=1 \ --log-bin=mysql-bin \ --binlog-format=ROW \ --binlog-row-image=FULL \ --sync_binlog=1 \ --gtid-mode=ON \ --enforce-gtid-consistency=ON

3.2 主库关键配置解析

  1. binlog-row-image=FULL:确保所有列数据都写入binlog,避免从库更新时因缺少字段报错
  2. sync_binlog=1:每次事务提交都同步binlog到磁盘,牺牲部分性能保证数据安全
  3. GTID模式:全局事务标识符能简化故障转移和位置追踪

3.3 创建复制账户

进入主库容器执行:

CREATE USER 'repl'@'172.28.5.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.28.5.%'; ALTER USER 'repl'@'172.28.5.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123';

血泪教训:MySQL 8默认使用caching_sha2_password插件,必须显式指定mysql_native_password,否则从库连接会报"Authentication plugin error"。

4. 从库配置与同步启动

4.1 从库容器启动

docker run -d --name mysql-slave \ --network mysql-replication-net \ --ip 172.28.5.11 \ -v mysql-slave-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=Slave@123 \ mysql:8.0 \ --server-id=2 \ --log-bin=mysql-bin \ --binlog-format=ROW \ --gtid-mode=ON \ --enforce-gtid-consistency=ON \ --skip-slave-start

4.2 配置主从连接

获取主库GTID位置:

SHOW MASTER STATUS\G -- 记录Executed_Gtid_Set值如:3a59f153-4f4e-11ec-9a1e-0242ac110002:1-10

在从库执行CHANGE MASTER命令:

CHANGE MASTER TO MASTER_HOST='172.28.5.10', MASTER_USER='repl', MASTER_PASSWORD='Repl@123', MASTER_AUTO_POSITION=1; START SLAVE;

4.3 验证复制状态

关键指标检查:

SHOW SLAVE STATUS\G -- Slave_IO_Running: Yes -- Slave_SQL_Running: Yes -- Seconds_Behind_Master: 0 -- Retrieved_Gtid_Set与Executed_Gtid_Set应与主库匹配

5. 深度踩坑实录

5.1 时区不一致导致timestamp字段异常

现象:主库插入的timestamp字段在从库显示不同值 解决方案:

# 启动容器时统一时区 -e TZ=Asia/Shanghai --default-time-zone='+8:00'

5.2 大事务导致复制中断

错误日志:"Worker 1 failed executing transaction..." 处理方法:

-- 主库配置 SET GLOBAL binlog_group_commit_sync_delay = 100; SET GLOBAL binlog_group_commit_sync_no_delay_count = 10; -- 从库恢复 STOP SLAVE; SET GLOBAL sql_slave_skip_counter=1; START SLAVE;

5.3 容器重启后复制失效

根本原因:从库的master.info未持久化 解决方案:

# 创建专用配置卷 docker volume create mysql-slave-conf # 启动时挂载配置文件 -v mysql-slave-conf:/etc/mysql/conf.d \ --relay-log=slave-relay-bin \ --relay-log-index=slave-relay-bin.index

6. 完整验证方案

6.1 基础数据同步测试

-- 主库操作 CREATE DATABASE replica_test; USE replica_test; CREATE TABLE users(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50)); INSERT INTO users(name) VALUES('测试用户'); -- 从库验证 SELECT * FROM replica_test.users;

6.2 故障转移演练

模拟主库宕机:

docker stop mysql-master -- 从库提升为主库 STOP SLAVE; RESET SLAVE ALL; SET GLOBAL read_only=OFF;

6.3 延迟压力测试

使用sysbench制造负载:

sysbench oltp_read_write \ --db-driver=mysql \ --mysql-host=172.28.5.10 \ --mysql-user=root \ --mysql-password=Master@123 \ --mysql-db=replica_test \ --tables=5 \ --table-size=100000 \ --time=300 \ --threads=16 \ --report-interval=10 \ run

监控从库延迟:

-- 在从库执行 SHOW SLAVE STATUS\G -- 观察Seconds_Behind_Master波动

7. 性能优化建议

7.1 容器资源限制

# 主库容器启动时添加 --memory=4g --memory-swap=4g \ --cpus=2 \ --blkio-weight=500

7.2 MySQL参数调优

主库my.cnf追加:

innodb_flush_log_at_trx_commit=1 innodb_buffer_pool_size=2G binlog_group_commit_sync_delay=100 binlog_group_commit_sync_no_delay_count=10

从库my.cnf追加:

read_only=ON slave_parallel_workers=4 slave_parallel_type=LOGICAL_CLOCK

7.3 监控方案

推荐使用Prometheus+mysqld_exporter+Grafana组合,关键监控指标:

  • 复制延迟(seconds_behind_master)
  • IO/SQL线程状态(slave_io_running, slave_sql_running)
  • 网络往返时间(rtt)
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进