MySQL8.0.43在anolis8.10容器化双主部署
系统:anolis8.10
镜像版本:MySQL8.0.43
第一步:停止并删除现有 MySQL 容器
分别在 LongXi110 和 LongXi111 上执行:docker ps | grep mysql
如果发现有其他运行中的容器:
停止容器(假设容器名为 mysql-node1 / mysql-node2)
docker stop mysql-node1
docker stop mysql-node2
删除容器(连同其存储层一起删除)
docker rm mysql-node1
docker rm mysql-node2
第二步:准备新的 MySQL 配置文件(my.cnf)
我们需要在两台机器上分别准备好双主配置的 my.cnf 文件,以便在创建容器时挂载进去。
node1
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
log-slave-updates = ON
auto-increment-offset = 1
auto-increment-increment = 2
sync-binlog = 1
innodb_flush_log_at_trx_commit = 1
host-cache-size=0
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
#!includedir /etc/mysql/conf.d/
node2
[mysqld]
server-id = 2
log-bin = mysql-bin
binlog-ignore-db = mysql
binlog-ignore-db = information_schema
binlog-ignore-db = performance_schema
binlog-ignore-db = sys
log-slave-updates = ON
auto-increment-offset = 2
auto-increment-increment = 2
sync-binlog = 1
innodb_flush_log_at_trx_commit = 1
host-cache-size=0
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
#!includedir /etc/mysql/conf.d/
第三步:创建并启动新的 MySQL 容器
node1:
docker run -d \
--name mysql-node1 \
--restart always \
-p 3306:3306 \
-v /opt/mysql/mysql_data:/var/lib/mysql \ #引号左边填你要挂载的数据目录
-v /root/docker-mysql/mysql/conf:/etc/mysql/conf.d \ #引号左边填你要挂载的my.cnf的位置
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.43
node2:
docker run -d \
--name mysql-node2 \
--restart always \
-p 3306:3306 \
-v /opt/mysql/mysql_data:/var/lib/mysql \ #引号左边填你要挂载的数据目录
-v /root/docker-mysql/mysql/conf:/etc/mysql/conf.d \ #引号左边填你要挂载的my.cnf的位置
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.43
第四步:验证容器启动和配置生效
分别进入两个容器,检查配置是否正确加载。
# 在 LongXi110 上
docker exec -it mysql-node1 mysql -uroot -p
# 输入密码后执行:
SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'auto_increment_offset';
SHOW VARIABLES LIKE 'auto_increment_increment';
预期结果:
-
server_id = 1
-
log_bin = ON
-
auto_increment_offset = 1
-
auto_increment_increment = 2
同样的方法检查 node2,预期 server_id = 2,offset = 2,increment = 2。
第五步:登录各自 MySQL 容器
# 在 LongXi110 上
docker exec -it mysql-node1 mysql -uroot -p
# 在 LongXi111 上
docker exec -it mysql-node2 mysql -uroot -p
在 node1 (110) 上:
CREATE USER 'repl_user'@'192.168.199.%' IDENTIFIED WITH mysql_native_password BY '你的强密码';
#'%'的意思是任意,各位参照自己的ip修改前三位
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.199.%';
FLUSH PRIVILEGES;
在 node2 (111) 上:
CREATE USER 'repl_user'@'192.168.199.%' IDENTIFIED WITH mysql_native_password BY '你的强密码';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.199.%';
FLUSH PRIVILEGES;
配置 CHANGE MASTER TO
在 node1 (110) 上查看:
SHOW MASTER STATUS;
记下 File 和 Position 的值,例如 mysql-bin.000001 和 157。
在 node2 (111) 上查看:
SHOW MASTER STATUS;
同样记下 File 和 Position 的值。
配置相互的主从关系:
在 node1 (110) 上,配置指向 node2 (111):
CHANGE MASTER TO
MASTER_HOST = '192.168.199.111',
MASTER_USER = 'repl_user',
MASTER_PASSWORD = '你的强密码',
MASTER_LOG_FILE = 'mysql-bin.000001', -- 替换为你在 node2 上 SHOW MASTER STATUS 得到的 File
MASTER_LOG_POS = 157; -- 替换为对应的 Position
在 node2 (111) 上,配置指向 node1 (110):
CHANGE MASTER TO
MASTER_HOST = '192.168.199.110',
MASTER_USER = 'repl_user',
MASTER_PASSWORD = '你的强密码',
MASTER_LOG_FILE = 'mysql-bin.000001', -- 替换为你从node1获取的File值
MASTER_LOG_POS = 157; -- 替换为你从node1获取的Position值
启动从库复制
在两个节点上分别执行:
START SLAVE;
验证复制状态
这是最关键的一步,确保一切正常。
在两个节点上分别执行:
SHOW SLAVE STATUS\G
检查输出中的两个关键指标,它们都必须显示为 Yes:
-
Slave_IO_Running: Yes -
Slave_SQL_Running: Yes
如果出现 No 或 Connecting,请根据 Last_IO_Error 或 Last_SQL_Error 的提示排查问题(常见原因:网络不通、密码错误、防火墙、MASTER_LOG_FILE/POS 不正确)。
验证双主功能
现在,你可以进行简单的测试:
-
在
node1上创建一个数据库或表,插入一条数据。 -
立即登录
node2,查看该数据库和表是否存在,数据是否同步。 -
反过来,在
node2上插入另一条数据。 -
回到
node1查看,新数据也应该同步过来了。
如果以上测试都通过,恭喜你,双主复制配置成功!auto-increment-offset 和 auto-increment-increment 的设置确保了即使两边同时插入数据,也不会产生主键冲突。


附:如果node1和node2的数据不同步,得先强行同步!
在 node1 上导出数据(包含所有库):
docker exec mysql-node1 mysqldump -uroot -p --all-databases --source-data=2 > /tmp/full_dump.sql
将 dump 文件传到 node2 所在机器(或用共享卷):
scp /tmp/full_dump.sql root@192.168.199.111:/tmp/
在 node2 上导入数据:
docker exec -i mysql-node2 mysql -uroot -p < /tmp/full_dump.sql
导入后,重新配置复制(因为 dump 包含了 CHANGE MASTER TO 语句,但为了保险,手动重配):
node1,node2分别执行:
STOP SLAVE;
RESET SLAVE ALL;
CHANGE MASTER TO
MASTER_HOST='192.168.199.110',
MASTER_USER='repl_user',
MASTER_PASSWORD='你的密码',
MASTER_LOG_FILE='mysql-bin.xxxxxx', -- SHOW MASTER STATUS;获取
MASTER_LOG_POS=xxxx; -- SHOW MASTER STATUS;获取
START SLAVE;
这种方法的缺点是停机时间长,且需要处理双向同步的顺序。 对于实验环境,更推荐先排查配置问题。
关机前操作(在两台机器上都做)
1. 进 MySQL,停掉复制线程(可选但稳妥)
STOP SLAVE;
不停也行,MySQL 重启后会自动从 relay-log 和恢复点继续跑,但主动停一下更干净,避免关机过程中 relay-log 写到一半。
2. 记一下当前 binlog 位置(方便下次出问题回查)
SHOW MASTER STATUS\G
SHOW SLAVE STATUS\G
把 Master_Log_File / Read_Master_Log_Pos / Exec_Master_Log_Pos 抄下来或截图,下次开机对得上就说明没丢。
3. 退出容器,停 MySQL 服务(比直接关宿主机温柔)
# 容器内
mysqladmin -uroot -p shutdown
# 或者宿主机直接
docker stop mysql-node1
两台都停完,再关宿主机。
下次开机后的恢复流程
1. 启动容器
docker start mysql-node1 # 110
docker start mysql-node2 # 111
如果当初 run 时加了 --restart always,开机自动就起了,这步可以省。
2. 进 MySQL 验状态
SHOW SLAVE STATUS\G
看两个指标:
-
Slave_IO_Running: Yes -
Slave_SQL_Running: Yes
如果都是 Yes,Seconds_Behind_Master 很快掉到 0,说明双主自动续上了,不用动。
3. 如果 IO/SQL 不是 Yes(极少情况)
START SLAVE;
一般就能拉起来,因为 master.info 和 relay-log 都在,位置没丢。
4. 验数据同步
node1 插一行,node2 查一下,通了就继续实验。
几个下次开机容易踩的小坑
-
宿主机 IP 变了:如果 192.168.199.110/111 是 DHCP 分配的,关机再开可能 IP 漂了,双主就会连不上。建议龙蜥里把这两台 IP 设成静态,或者在路由器/DHCP 里绑 MAC。
-
防火墙:龙蜥默认 firewalld 如果开了,3306 得放行,不然 IO 线程
Connecting。 -
容器时区/时间:如果宿主机时间跳变大,binlog 时序没事,但你自己看
SHOW SLAVE STATUS的时间戳会乱,不影响复制。

浙公网安备 33010602011771号