当前位置: 首页 > news >正文

MySQL 主从复制 — Docker 双机灾备方案

MySQL 主从复制 — Docker 双机灾备方案

场景:两台服务器,各跑一个 MySQL Docker 容器
目的:主库挂了从库顶上,防止数据丢失


🏗️ 环境

项目主库服务器从库服务器
IP192.168.1.100192.168.1.101
容器名mysql_mastermysql_slave
数据目录/data/mysql/master/data/mysql/slave

第一部分:主库服务器操作

步骤 1:拉镜像 + 建数据目录

# 主库服务器上执行dockerpull mysql:5.6.51# 创建数据持久化目录(容器删了数据还在)mkdir-p/data/mysql/master

步骤 2:启动主库容器(带 binlog 配置)

dockerrun-d\--namemysql_master\--restartalways\-p3306:3306\-v/data/mysql/master:/var/lib/mysql\-eMYSQL_ROOT_PASSWORD=你的密码\mysql:5.6.51\--log-bin=mysql-bin\--server-id=1\--binlog-format=ROW\--expire-logs-days=7

--restart always= 服务器重启后容器自动启动
-v挂载数据目录 = 容器删了重跑数据还在

验证

dockerexecmysql_master mysql-uroot-p'你的密码'-e"SHOW MASTER STATUS;"

正常输出:

+------------------+----------+--------------+------------------+ | File | Position | ... | | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 120 | | | +------------------+----------+--------------+------------------+

步骤 3:建复制用户

dockerexecmysql_master mysql-uroot-p'你的密码'-e" CREATE USER 'replicator'@'%' IDENTIFIED BY 'repl_password'; GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%'; FLUSH PRIVILEGES;"

步骤 4:确认主库容器 IP

dockerinspect mysql_master--format'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'

记下这个 IP(例如172.17.0.2)。


第二部分:从库服务器操作

步骤 1:建数据目录 + 启动从库容器

# 从库服务器上执行dockerpull mysql:5.6.51mkdir-p/data/mysql/slavedockerrun-d\--namemysql_slave\--restartalways\-p3306:3306\-v/data/mysql/slave:/var/lib/mysql\-eMYSQL_ROOT_PASSWORD=你的密码\mysql:5.6.51\--server-id=2

步骤 2:把主库数据复制到从库

⚠️重点:从库开始复制之前,数据必须和主库当时的状态一致

在主库服务器上导出

# 主库服务器执行dockerexecmysql_master mysqldump-uroot-p'你的密码'\--all-databases --master-data --single-transaction>/tmp/master_dump.sql# 查看 dump 文件里记录的 binlog 位置grep"MASTER_LOG_POS"/tmp/master_dump.sql# 会输出类似: CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=494;

传到从库服务器

# 主库服务器执行scp/tmp/master_dump.sql root@192.168.1.101:/tmp/

在从库服务器上恢复

# 从库服务器执行dockerexec-imysql_slave mysql-uroot-p'你的密码'</tmp/master_dump.sql

步骤 3:配置从库连接主库

dockerexecmysql_slave mysql-uroot-p'你的密码'-e" CHANGE MASTER TO MASTER_HOST = '主库服务器IP', MASTER_PORT = 3306, MASTER_USER = 'replicator', MASTER_PASSWORD = 'repl_password', MASTER_LOG_FILE = 'mysql-bin.xxxxxx', MASTER_LOG_POS = xxxx; START SLAVE;"

⚠️ 把以下 2 项替换成你主库SHOW MASTER STATUS输出的真实值:

  • MASTER_LOG_FILE→ 替换mysql-bin.xxxxxx
  • MASTER_LOG_POS→ 替换xxxx

⚠️MASTER_HOST主库服务器的宿主机 IP(不是容器内部 IP)
Docker 容器跨服务器通信用宿主机 IP + 端口映射

步骤 4:验证复制状态

dockerexecmysql_slave mysql-uroot-p'你的密码'-e"SHOW SLAVE STATUS\G"

⚠️ 常见误区SHOW SLAVE STATUS不是查某张表的,而是查复制管道通不通

SHOW SLAVE STATUS 怎么看

Slave_IO_Running: Yes ← 从库到主库的网络连接正常吗? Slave_SQL_Running: Yes ← 从库在正常执行同步吗? Seconds_Behind_Master: 0 ← 延迟几秒?(0 = 实时同步) Last_Error: ← 有没有报错?

比喻理解

主库 ────────→ 从库 Slave_IO_Running: Yes → 快递员在正常取件 Slave_SQL_Running: Yes → 快递员在正常派件 Seconds_Behind_Master: 0 → 当天件当天送完 Last_Error: 空 → 没有包裹损坏

要查具体某张表有没有同步,需要单独查

-- 主库查SELECTCOUNT(*)FROM你的表名;-- 从库查SELECTCOUNT(*)FROM你的表名;

两条数一样 → 那张表同步好了。

关键检查项

字段必须等于含义
Slave_IO_RunningYes从库在正常拉取主库日志
Slave_SQL_RunningYes从库在正常回放日志
Seconds_Behind_Master0延迟 0 秒(实时同步)
Last_Error没有报错

如果有任何No,查看Last_IO_ErrorLast_SQL_Error看具体原因。


第三部分:验证同步

主库写入数据(在主库服务器上执行):

dockerexecmysql_master mysql-uroot-p'你的密码'-e" CREATE DATABASE test_sync; USE test_sync; CREATE TABLE t1 (id INT, msg VARCHAR(50)); INSERT INTO t1 VALUES (1, '数据已同步');"

从库查询(在从库服务器上执行):

dockerexecmysql_slave mysql-uroot-p'你的密码'-e"SELECT * FROM test_sync.t1;"

如果输出1 | 数据已同步主从复制正常工作


第四部分:主库故障切换(最重要的操作)

场景:主库服务器宕机了,怎么办?

步骤 1:确认从库已追上主库

# 在从库服务器上执行dockerexecmysql_slave mysql-uroot-p'你的密码'-e"SHOW SLAVE STATUS\G"

找这句:Slave_SQL_Running_State: Slave has read all relay log
→ 说明所有数据已追平

步骤 2:将从库提升为新主库

dockerexecmysql_slave mysql-uroot-p'你的密码'-e" STOP SLAVE; RESET SLAVE ALL;"# 删掉容器重新以主库模式启动dockerstop mysql_slavedockerrmmysql_slavedockerrun-d\--namemysql_new_master\--restartalways\-p3306:3306\-v/data/mysql/slave:/var/lib/mysql\-eMYSQL_ROOT_PASSWORD=你的密码\mysql:5.6.51\--log-bin=mysql-bin\--server-id=2\--binlog-format=ROW

步骤 3:切换应用连接

把应用里的数据库连接 IP 从192.168.1.100改成192.168.1.101,重启应用。


第五部分:Docker 注意事项

容器重启策略

dockerupdate--restartalways mysql_masterdockerupdate--restartalways mysql_slave

数据备份

cargorun--release--manifest-path mysql_backup/Cargo.toml -- backup\--userroot--password你的密码\--dockermysql_master\--keep-days30\--output/backups/mysql

日常检查命令速查表

操作命令
查看主库状态docker exec mysql_master mysql -uroot -p密码 -e "SHOW MASTER STATUS\G"
查看从库状态docker exec mysql_slave mysql -uroot -p密码 -e "SHOW SLAVE STATUS\G"
停止复制docker exec mysql_slave mysql -uroot -p密码 -e "STOP SLAVE;"
恢复复制docker exec mysql_slave mysql -uroot -p密码 -e "START SLAVE;"
进入 MySQLdocker exec -it mysql_master mysql -uroot -p密码
查看日志docker logs mysql_master --tail 50

第六部分:常见问题与排错

问题 1:Slave_IO_Running: No

现象

Slave_IO_Running: No Last_IO_Error: error connecting to master 'replicator@主库IP:3306' - retry-time: 60

原因:从库连不上主库

排查步骤

# 1. 在从库服务器上测试网络通不通ping主库服务器IP# 2. 测试端口通不通telnet 主库服务器IP3306# 或nc-zv主库服务器IP3306# 3. 检查主库容器是否在运行dockerps|grepmysql_master# 4. 检查主库是否监听了 0.0.0.0dockerexecmysql_master mysql-uroot-p密码-e"SHOW VARIABLES LIKE 'bind_address';"# 5. 检查复制用户和密码dockerexecmysql_master mysql-uroot-p密码-e"SELECT user, host FROM mysql.user WHERE user='replicator';"

解决

  • 防火墙没开 3306 端口 → 开防火墙
  • Docker 端口映射不对 →docker run时加-p 3306:3306
  • MySQL 只绑了 127.0.0.1 → 改为bind_address = 0.0.0.0
  • 密码错了 →ALTER USER 'replicator'@'%' IDENTIFIED BY '正确密码';

问题 2:Slave_SQL_Running: No

现象

Slave_SQL_Running: No Last_SQL_Error: Error 'Table 'xxx' doesn't exist' on query. ...

原因:从库缺了某张表(通常是复制前没同步老数据)

解决

方法 A:跳过这条错误(紧急恢复复制)

STOP SLAVE;SETGLOBALSQL_SLAVE_SKIP_COUNTER=1;STARTSLAVE;

重复直到错误消失。这会导致被跳过的数据丢失。

方法 B:重新同步(最彻底)

# 1. 主库重新导出(带 --master-data 自动记录位置)dockerexecmysql_master mysqldump-uroot-p密码\--all-databases --master-data --single-transaction>/tmp/full_dump.sql# 2. 从库重置dockerexecmysql_slave mysql-uroot-p密码-e"STOP SLAVE; RESET SLAVE ALL;"# 3. 从库重新导入dockerexec-imysql_slave mysql-uroot-p密码</tmp/full_dump.sql# 4. 重新配置复制(用 dump 文件自带的位置自动配置)# --master-data 参数会在 dump 最前面写入 CHANGE MASTER 语句# 直接启动就行(如果 dump 里带了 CHANGE MASTER)dockerexecmysql_slave mysql-uroot-p密码-e"START SLAVE;"

问题 3:Seconds_Behind_Master 越来越大

现象:延迟从 0 秒慢慢涨到几秒、几分钟、几小时

原因

  • 从库服务器性能比主库差(CPU / 磁盘 IO 跟不上)
  • 主库有大事务(如一次性删 100 万行)
  • 网络带宽不够

解决

# 1. 检查从库资源dockerstats mysql_slave --no-stream# 2. 检查主库是否有长时间运行的查询dockerexecmysql_master mysql-uroot-p密码-e"SHOW PROCESSLIST;"# 3. 临时方案:从库追上来后会自己恢复# 4. 长期方案:升级从库服务器配置

问题 4:主库容器重启后复制中断

现象:主库 Docker 重启后,从库Slave_IO_Running: Connecting

原因:主库 Docker 重启后 IP 变了(宿主机重启或 Docker 网络重建)

解决

# 1. 查看主库新 IPdockerinspect mysql_master--format'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'# 2. 从库重新指向新 IPdockerexecmysql_slave mysql-uroot-p密码-e" STOP SLAVE; CHANGE MASTER TO MASTER_HOST = '新IP'; START SLAVE;"

预防:如果是跨服务器,不要用容器 IP,用宿主机 IP + 端口映射

问题 5:主键冲突导致复制中断

现象

Last_SQL_Error: Duplicate entry 'xxx' for key 'PRIMARY'

原因:从库也写了数据(read_only没开),导致主键冲突

解决

# 1. 确保从库只读dockerexecmysql_slave mysql-uroot-p密码-e"SET GLOBAL read_only = ON;"# 2. 跳过冲突STOP SLAVE;SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;START SLAVE;

问题 6:binlog 写满磁盘

现象:主库磁盘满了,MySQL 无法写入

原因expire-logs-days没设或设太大

解决

# 1. 查看当前 binlogdockerexecmysql_master mysql-uroot-p密码-e"SHOW BINARY LOGS;"# 2. 手动清理已经同步过的 binlogdockerexecmysql_master mysql-uroot-p密码-e"PURGE BINARY LOGS TO 'mysql-bin.000010';"# 3. 预防:容器启动时加 --expire-logs-days=7

问题 7:GTID 相关错误

现象

Last_IO_Error: The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.

原因:主库清理了从库还没同步的 binlog

解决

# 从库重新指向当前 binlog 位置(跳到最新)dockerexecmysql_slave mysql-uroot-p密码-e" STOP SLAVE; CHANGE MASTER TO MASTER_AUTO_POSITION = 0; START SLAVE;"

排错检查清单

当复制出问题时,按顺序排查:

□ 从库能 ping 通主库吗? □ 主库 3306 端口能 telnet 通吗? □ 主库容器在运行吗?(docker ps) □ 主库 binlog 开启了吗?(SHOW MASTER STATUS) □ 复制用户存在且密码正确吗? □ 防火墙放行了 3306 吗? □ 从库数据是否和主库一致? □ Slave_IO_Running 和 Slave_SQL_Running 分别是什么? □ Last_IO_Error 和 Last_SQL_Error 说了什么?
http://www.cnnetsun.cn/news/2654975.html

相关文章:

  • 从手动到自动化:如何用YARN REST API和脚本优雅管理大批量任务的生命周期
  • 神经渲染相机轨迹优化:从理论到实战的完整指南
  • Ceph OSD NUMA 亲和性、Page Cache 跨 NUMA 访问与绑核实践
  • 掌握AMD Ryzen处理器的终极武器:SMUDebugTool深度解析
  • 验收驱动提示词:让企业 AI 输出可控、可复用
  • Jellyfin Android TV终极配置指南:15分钟打造完美家庭影院体验
  • 别再只盯着路由模式了!天融信防火墙透明模式部署实战,零感知保护内网安全
  • 给程序员的气象学:用代码思维图解大气环流三圈模型(哈德来/费雷尔/极地环流)
  • 3步搞定飞书文档批量导出:告别手动下载的烦恼
  • 数学建模‘小白’避坑指南:如何从一份居民健康问卷中挖掘出靠谱结论?
  • AI Agent 越来越强,但谁来为它的行为负责?KYA 给出答案
  • 从智能镊子到LCR表:深入拆解‘交流响应法’与‘直流充放电法’如何各显神通
  • 输入冲突终结者:Hitboxer SOCD键盘重映射工具的架构解析与实战指南
  • Get-cookies.txt-LOCALLY:3分钟掌握浏览器Cookie本地导出终极指南
  • 如何用开源阅读鸿蒙版打造你的专属数字图书馆:5个步骤告别碎片化阅读
  • GPT-4深度解析:从MoE架构到智能体应用的技术跃迁
  • MyTV-Android:老旧电视重获新生的终极直播解决方案
  • 魔兽争霸3现代化改造指南:开源工具Warcraft Helper完全解析
  • 汽车技术趋势解析:从电动化、智能化到软件定义汽车的未来
  • CXLE83260H 高精度 LED 恒流驱动芯片
  • 异构图神经网络加速器的内存效率优化与硬件设计
  • 3步搞定番茄小说下载器:离线阅读全平台解决方案
  • 27考研石雷鹏作文|七步法网课PDF
  • DeepSeek LeetCode 2842. 统计一个字符串的 k 子序列美丽值最大的数目 TypeScript实现
  • 从GPT-Neo到FFmpeg:构建AI虚拟主播的完整技术栈解析
  • 现代网络安全实战框架:技术、流程与人员三大支柱解析
  • 路由器是工作在OSI模型**网络层(第3层)**的网络设备,其核心功能是根据数据包中的**目的IP地址**
  • SMUDebugTool:免费开源AMD Ryzen处理器调试工具完整指南
  • 综合算法 XXIX | 网络与算法
  • 如何高效管理Windows右键菜单:个性化定制完整教程