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-replication2.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_ci3.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: YesSlave_SQL_Running: YesSeconds_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从库异常时重建流程:
- 停止从库服务
- 清空数据目录:
rm -rf ~/docker-mysql-replication/slave/data/* - 从主库备份恢复数据
- 重新配置复制关系
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 = 107.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: slavepass8. 扩展架构建议
当单从库无法满足读需求时,可以:
横向扩展多个从库
# 启动第二个从库(端口映射改为3308) docker run -d --name mysql-slave-2 -p 3308:3306 ...搭建级联复制
主库 -> 从��1 -> 从库2考虑GTID复制模式(适合复杂拓扑)
-- 主库启用GTID gtid_mode=ON enforce_gtid_consistency=ON -- 从库配置 CHANGE MASTER TO MASTER_AUTO_POSITION=1;这套Docker化的MySQL主从复制方案,我已经在十几个项目中实际应用过。最大的优势是开发环境的真实性——你能在本地完全模拟生产架构,而资源消耗仅为传统方案的1/10。对于需要快速验证数据库架构的团队,这绝对是性价比最高的选择。