《MySQL进阶(十二):集群架构与实践专题(二)》
主从复制配置
以下⽰例中使⽤⼀主两从架构,当往主服务器中写⼊数据时,从服务器可以实现⾃动同步,查询时 可以在任⼀节点获取数据

服务器规划
- 在单台服务器上使⽤ Docker 模拟多台服务器的场景
- 主从服务器IP⼀致,端⼝号不同

- 主服务器:容器名bit-mysql-master 端⼝号 53306
- 从服务器1:容器名bit-mysql-slave1 ,端⼝号 53307
- 从服务器2:容器名 bit-mysql-slave2 ,端⼝号 53308
注意:启动docker前先关闭防⽕墙
主库配置
创建并启动MySQL主服务器
- Docker 中的 MySQL 服务的端口号 3306 映射到宿主机端口 53306
- Docker 中的配置文件路径映射到宿主机的
/bit/mysql/master/conf目录 - Docker 中的数据目录映射到宿主机的
/bit/mysql/master/mysql目录Docker 中 MySQL 的 root 密码为 123456 - Docker 中 MySQL 主库容器命名为
bit-mysql-master - Docker 中的 MySQL 版本为 mysql:8.0.41
1. 端口格式含义
-p 宿主机端口:容器内端口比如 53308:3306:
- 后面的
3306:容器内 MySQL 的默认端口(MySQL 本身固定,不能乱改,改了容器内服务起不来); - 前面的
53308:宿主机的端口(给这个容器分配的 “对外门牌号”)。
2. 为啥前面是 53308?为啥加 5?
- 这纯粹是人为习惯,方便管理:主库用了
53306,从库 1 用53307,从库 2 用53308—— 只是按 “主库端口 + 1” 的规律递增,好记(比如一看 53306 就知道是主库,53307/53308 是从库)。 - 你完全可以改成其他数字,比如主库用
60000,从库 1 用60001,从库 2 用60002,只要满足两个条件:① 宿主机上这个端口没被其他程序占用(比如不能同时用两个53306);② 端口在 0-65535 范围内。 - 为啥大家常从 5 开头?因为 1-1023 是 “知名端口”(比如 80 是 HTTP、443 是 HTTPS、3306 是 MySQL 默认),避免和这些常用端口冲突,所以优先用 1024 以上的端口,5 开头只是顺手选的,没有特殊含义。
1. 映射的核心目的:“数据 / 配置持久化”+“方便修改”
- Docker 容器的特点是临时存储—— 如果你直接在容器里创建文件、修改配置,一旦容器被删除(比如
docker rm),里面的所有数据、配置都会丢失! - 而
-v 宿主机目录:容器内目录就是 “把容器的关键目录绑定到宿主机”,相当于给容器的目录开了个 “后门”,让数据 / 配置存在宿主机上,永远不会丢。
| 映射命令 | 作用 |
|---|---|
-v /bit/mysql/slave2/conf:/etc/mysql/conf.d | 把 “从库 2 的配置目录” 绑定到宿主机的 /bit/mysql/slave2/conf |
-v /bit/mysql/slave2/mysql:/var/lib/mysql | 把 “从库 2 的数据库数据目录” 绑定到宿主机的 /bit/mysql/slave2/mysql |
简单说:
- 配置映射:以后改从库 2 的 MySQL 配置(比如
my.cnf),不用进入容器,直接在宿主机(/bit/mysql/slave2/conf)里改就行; - 数据映射:从库 2 的数据库表、数据,实际存在宿主机
(/bit/mysql/slave2/mysql)里,就算容器删了,重新创建容器时再映射这个目录,数据还在。
2. 要不要先在宿主机建立目录?
建议先在宿主机手动创建! (不创建也能执行命令,但会有坑)
- 如果你没创建,执行
docker run -v 宿主机目录:容器内目录时,Docker 会自动帮你在宿主机创建这个目录,但目录的「权限可能不对」(比如所有者是 root,容器内 MySQL 进程没权限读写,导致服务启动失败)。 - 正确做法(实操步骤):先在宿主机执行命令,创建目录并给对权限(以从库 2 为例):

3.容器里要不要建这个文件?
不需要! 映射后,容器内的 /etc/mysql/conf.d 和 /var/lib/mysql 目录,本质是「宿主机目录的 “镜像”」—— 宿主机目录里有啥,容器内就有啥;宿主机没有的,容器内也没有(除非宿主机目录为空,容器启动时会自动生成默认文件,比如 MySQL 的默认配置)。
比如你要给从库 2 加 my.cnf 配置文件:
- 直接在宿主机的
/bit/mysql/slave2/conf里创建my.cnf,写好配置; - 容器内的
/etc/mysql/conf.d里会自动出现这个文件(因为映射了),不用在容器里再创建。
4. 宿主机改配置和容器改配置,都能生效吗?文件存在哪?
- 双向同步生效:不管是在宿主机改,还是进入容器改,两边都会同步更新!比如:在宿主机
/bit/mysql/slave2/conf里改了my.cnf,容器内/etc/mysql/conf.d/my.cnf会立刻同步;反之,进入容器改了这个文件,宿主机的文件也会变。 - 文件本质存在宿主机上:映射后,容器内的目录只是 “访问宿主机目录的入口”,实际的文件存储在宿主机的
/bit/mysql/slave2/conf和/bit/mysql/slave2/mysql里。就算你删除容器,宿主机的目录和文件还在;下次重新创建容器时,只要再映射同一个宿主机目录,之前的配置和数据都会恢复。
53306 是 “容器 MySQL 在主机上的专属转发入口”:
- 唯一作用:让外部程序(Navicat、代码等)能找到容器 MySQL;
- 核心规则:53306 不能被 Docker 之外的程序占用,且访问时需要容器 MySQL 的用户名密码;
- 实际效果:多个合法程序可同时通过 53306 访问容器 MySQL,和主机 MySQL(3306)完全隔离。
进⼊Docker容器

创建配置⽂件
在宿主机的主服务器配置映射⽬录 /bit/mysql/master/conf 中创建配置⽂件 my.cnf ,并完成以下配置

重启主库MySQL容器,使配置⽣效

- 先进入主库容器:
docker exec -it bit-mysql-master bash - 登录 MySQL:
mysql -u root -p123456 - 再执行 SQL 命令:
select @@server_id;查看主库的server-id配置是否生效
配置主服务器
创建从库复制专用账号
主库必须创建一个授权账号,从库才能通过该账号连接主库同步数据,执行 SQL:

查看⽤⼾是否⽣效

查看主库状态并记录关键信息
执行命令获取主库二进制日志位置,从库配置必须用到这两个值:
SHOW MASTER STATUS;- 记录 File 和 Position 的值,之后要在从服务器中配置中⽤到这两个值,表⽰从哪个⽇志⽂件 中的哪个位置开始同步数据,所以在整个主从配置完成之前不要再操作主服务器,防⽌主服务器发⽣变化
- 到此主服务器配置完成。
从库配置
可以配置多台从服务器,⽐如slave1、slave2...
# 1. (必做)创建从库宿主机目录并授权(避免权限问题)
sudo mkdir -p /bit/mysql/slave1/conf /bit/mysql/slave1/mysql
sudo chmod -R 777 /bit/mysql/slave1# 2. 启动从库容器(先启容器,后续再配配置文件)
docker run -d \
--name bit-mysql-slave1 \
-p 53307:3306 \
-v /bit/mysql/slave1/conf:/etc/mysql/conf.d \
-v /bit/mysql/slave1/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.41# 3. (容器启动后)创建并写入从库配置文件my.cnf
sudo tee /bit/mysql/slave1/conf/my.cnf << 'EOF'
[mysqld]
server-id=2
relay-log=relay-bin
log-slave-updates=1
read-only=1
EOF# 4. 重启从库容器,让配置生效
docker restart bit-mysql-slave1# 5. 验证容器状态(确认启动成功)
docker ps | grep bit-mysql-slave1- 用
sudo避免目录创建 / 写入的权限问题,无需手动输入密码(若终端提示输入 sudo 密码,输入即可); - 用
tee命令替代vim,无需手动编辑,直接写入配置文件,更高效; - 执行完后,下一步就是进入从库容器连接主库,代码如下(后续执行):
# 进入从库容器并登录MySQL
docker exec -it bit-mysql-slave1 bash
mysql -u root -p123456在从服务器上配置主从关系在从机的执⾏以下SQL:

一、主库(Master)配置流程(仅需执行 1 次)
- 准备基础环境:宿主机创建主库的数据 / 配置目录(用于持久化,避免容器删除后数据丢失),并设置权限;
- 创建并启动主库容器:通过
docker run启动容器,关键参数必须带:--server-id=1(主库唯一 ID,不能与从库重复);--log_bin=mysql-bin(开启二进制日志,主从复制的核心依赖);
- 调整主库配置(可选但推荐):进入容器修改 MySQL 配置文件,优化日志、连接等参数(如设置
binlog_format=ROW,提升同步稳定性); - 创建复制专用账号:主库 MySQL 终端执行授权,允许从库远程连接并获取日志:

二、从库(Slave)配置流程(新增从库时重复执行)
- 准备基础环境:宿主机为每个从库创建独立的数据 / 配置目录(避免与主库、其他从库冲突),设置权限;
- 创建并启动从库容器:
docker run启动容器,关键参数:--server-id=2/3/4...(每个从库唯一 ID,不能重复,也不能等于主库);--read_only=1(设置从库只读,防止误写,root 用户除外);- 端口映射唯一(如
53306主库、53307slave1、53308slave2);
- 调整从库配置(可选):修改从库配置文件,优化中继日志、同步线程等参数;
- 与主库建立连接:从库 MySQL 终端执行
CHANGE MASTER TO,填入主库的 IP、端口、复制账号密码,以及主库的File和Position; - 启动复制并验证:执行
START SLAVE;,再用SHOW SLAVE STATUS\G;检查Slave_IO_Running和Slave_SQL_Running是否均为Yes,确认同步生效。
最后测试数据,在主库插入数据,查看从库中是否含有主库数据。
常⽤命令

常⻅问题
server-id 重复
- 修改 my.cnf 中的 sever_id 选项
连接主库失败
- 用户名密码错误
- 防火墙是否关闭
- 主服务器连接数过多
Replica_IO_Running: Connecting
- 检查防火墙是否关闭
- 复制用户的密码策略
- 重启从服务器的复制功能
- 检查复制账户是否可以登录主服务器
eplica_IO_Running: NO
- 根据错误码与错误信息排查相应的问题
binlog 日志损坏
- 备份主库并在从库恢复,重构主从关系
