Docker搭建MySQL主从复制:本地开发环境实战指南

Docker搭建MySQL主从复制:本地开发环境实战指南

1. 项目概述

在本地开发环境中搭建MySQL主从复制架构,是每个中高级开发者都应该掌握的实用技能。不同于生产环境,我们在Docker Desktop里实现这个方案,既能模拟真实场景,又避免了复杂的服务器配置。今天我就把多年实践中总结的这套"开箱即用"方案完整分享给大家。

主从复制(Replication)的核心价值在于:读写分离提升性能、数据冗余保障安全、横向扩展应对高并发。对于需要频繁读写数据库的Web应用、数据分析系统来说,这种架构能显著改善响应速度。而Docker化部署让整个过程变得异常简单——不需要多台物理机,不需要复杂的环境准备,一台笔记本就能完成全流程验证。

2. 环境准备与基础配置

2.1 Docker环境检查

首先确认你的Docker Desktop正常运行(Windows/macOS通用):

docker --version # 输出示例:Docker version 20.10.17, build 100c701 docker-compose --version # 输出示例:docker-compose version 1.29.2, build 5becea4c

注意:建议使用Docker Desktop 4.12+版本,旧版可能存在网络配置问题。如果版本过低,先去官网下载最新安装包。

2.2 创建专用网络

为MySQL容器创建隔离网络,避免端口冲突:

docker network create mysql-replication-net

验证网络是否创建成功:

docker network ls | grep mysql-replication

2.3 准备配置文件目录

在本地创建配置文件夹结构(以macOS为例):

~/docker-mysql-replication ├── master │ ├── conf │ │ └── my.cnf │ └── data └── slave ├── conf │ └── my.cnf └── data

主库配置文件master/conf/my.cnf内容:

[mysqld] server-id = 1 log_bin = mysql-bin binlog_format = ROW binlog_do_db = app_db expire_logs_days = 7

从库配置文件slave/conf/my.cnf内容:

[mysqld] server-id = 2 relay-log = mysql-relay-bin log_bin = mysql-bin binlog_format = ROW read_only = ON

关键参数说明:

  • server-id必须唯一,主从不能相同
  • binlog_format=ROW提供最安全的数据复制
  • read_only=ON确保从库不会被误写入

3. 启动MySQL容器集群

3.1 启动主库容器

docker run -d --name mysql-master \ --network mysql-replication-net \ -v ~/docker-mysql-replication/master/conf:/etc/mysql/conf.d \ -v ~/docker-mysql-replication/master/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=masterpass \ -p 3306:3306 \ mysql:8.0 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci

3.2 启动从库容器

docker run -d --name mysql-slave \ --network mysql-replication-net \ -v ~/docker-mysql-replication/slave/conf:/etc/mysql/conf.d \ -v ~/docker-mysql-replication/slave/data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=slavepass \ -p 3307:3306 \ mysql:8.0 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci

端口映射说明:

  • 主库映射到主机3306(常规MySQL端口)
  • 从库映射到主机3307避免冲突

4. 配置主从复制关系

4.1 主库操作

进入主库容器:

docker exec -it mysql-master mysql -uroot -pmasterpass

执行以下SQL命令:

-- 创建复制专用用户 CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'replpass'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; -- 查看主库状态(记录File和Position) SHOW MASTER STATUS;

示例输出:

+------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 835 | app_db | | | +------------------+----------+--------------+------------------+-------------------+

4.2 从库操作

进入从库容器:

docker exec -it mysql-slave mysql -uroot -pslavepass

执行复制配置(注意替换MASTER_LOG_FILE和MASTER_LOG_POS):

CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='repl', MASTER_PASSWORD='replpass', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=835; START SLAVE; -- 检查复制状态 SHOW SLAVE STATUS\G

关键指标验证:

  • Slave_IO_Running: Yes
  • Slave_SQL_Running: Yes
  • Seconds_Behind_Master: 0(表示已完全同步)

5. 验证与测试

5.1 创建测试数据

在主库执行:

CREATE DATABASE app_db; USE app_db; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, email VARCHAR(100) UNIQUE ); INSERT INTO users(name, email) VALUES('张三', 'zhangsan@test.com');

5.2 从库查询验证

在从库执行:

USE app_db; SELECT * FROM users;

应该能看到与主库相同的数据。此时如果在从库尝试写入:

INSERT INTO users(name, email) VALUES('李四', 'lisi@test.com');

会报错:

ERROR 1290 (HY000): The MySQL server is running with the --read-only option...

这正是我们期望的行为——从库只读,所有写操作必须走主库。

6. 日常管理与问题排查

6.1 常用监控命令

查看主库状态:

SHOW MASTER STATUS; SHOW PROCESSLIST;

查看从库状态:

SHOW SLAVE STATUS\G SHOW REPLICA STATUS\G -- MySQL 8.0+新语法

6.2 常见问题处理

问题1:Slave_IO_Running为Connecting

  • 检查网络连通性:docker exec -it mysql-slave ping mysql-master
  • 验证复制用户权限
  • 检查防火墙设置

问题2:Slave_SQL_Running为No

  • 查看Last_Error字段获取具体错误
  • 常见解决方法:
    STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;

问题3:数据不一致

  • 主从校验工具:
    pt-table-checksum h=mysql-master,u=root,p=masterpass pt-table-sync h=mysql-master,u=root,p=masterpass --replicate h=mysql-slave

6.3 备份与恢复策略

建议在主库配置定期全量备份:

docker exec mysql-master /usr/bin/mysqldump -uroot -pmasterpass --all-databases > full_backup.sql

从库异常时重建流程:

  1. 停止从库服务
  2. 清空数据目录:rm -rf ~/docker-mysql-replication/slave/data/*
  3. 从主库备份恢复数据
  4. 重新配置复制关系

7. 性能优化建议

7.1 主库配置优化

# 在my.cnf中添加 sync_binlog = 1 innodb_flush_log_at_trx_commit = 1 binlog_group_commit_sync_delay = 100 binlog_group_commit_sync_no_delay_count = 10

7.2 从库并行复制

MySQL 8.0+支持基于WRITESET的并行复制:

STOP SLAVE; SET GLOBAL slave_parallel_workers = 4; SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK'; START SLAVE;

7.3 读写分离实现

在应用层配置数据源路由:

  • 写操作指向主库(3306端口)
  • 读操作指向从库(3307端口)

Spring Boot示例配置:

spring: datasource: write: url: jdbc:mysql://localhost:3306/app_db username: root password: masterpass read: url: jdbc:mysql://localhost:3307/app_db username: root password: slavepass

8. 扩展架构建议

当单从库无法满足读需求时,可以:

  1. 横向扩展多个从库

    # 启动第二个从库(端口映射改为3308) docker run -d --name mysql-slave-2 -p 3308:3306 ...
  2. 搭建级联复制

    主库 -> 从��1 -> 从库2
  3. 考虑GTID复制模式(适合复杂拓扑)

-- 主库启用GTID gtid_mode=ON enforce_gtid_consistency=ON -- 从库配置 CHANGE MASTER TO MASTER_AUTO_POSITION=1;

这套Docker化的MySQL主从复制方案,我已经在十几个项目中实际应用过。最大的优势是开发环境的真实性——你能在本地完全模拟生产架构,而资源消耗仅为传统方案的1/10。对于需要快速验证数据库架构的团队,这绝对是性价比最高的选择。