# MySQL 主从磁盘满导致集群崩溃:故障复盘与恢复实录
MySQL 主从磁盘满导致集群崩溃故障复盘与恢复实录记录一次 MySQL 主从架构因 binlog 无限增长撑满磁盘导致主从全部崩溃的完整排障过程。环境背景组件版本/配置MySQL8.0.15部署方式Docker Swarm主从架构异机部署GTID 模式复制数据挂载/mroldx/data/mysql/data:/var/lib/mysql网络overlay networkbackend_net故障现象某天发现服务全部不可用排查发现主库宿主机磁盘 100% 占满binlog 文件累计约 200GB单文件 1GB近 200 个文件MySQL 进程因无法写入而崩溃Docker Swarm 反复拉起容器均失败从库复制中断恢复过程第一阶段抢救主库MySQL 无法启动只能直接操作宿主机文件系统。1. 确认 binlog 位置和状态ls-lh/mroldx/data/mysql/data/mysql-bin.*cat/mroldx/data/mysql/data/mysql-bin.indexdf-h/mroldx/data/mysql/data确认 binlog 文件从mysql-bin.000098到mysql-bin.000291每个约 1GB。2. 删除旧 binlog 释放空间保留最近的文件删除历史文件cd/mroldx/data/mysql/datasudormmysql-bin.000{098..280}注意bash 花括号展开在某些终端下可能有兼容性问题如果报错可以用for循环替代foriin$(seq98280);dosudorm-fmysql-bin.$(printf%06d$i);done3. 重建 binlog 索引文件这是关键步骤。删除 binlog 文件后必须同步更新mysql-bin.index否则 MySQL 启动时发现索引中的文件不存在会直接报错拒绝启动。sudosh-cecho ./mysql-bin.000281 /mroldx/data/mysql/data/mysql-bin.indexsudosh-cecho ./mysql-bin.000282 /mroldx/data/mysql/data/mysql-bin.indexsudosh-cecho ./mysql-bin.000283 /mroldx/data/mysql/data/mysql-bin.index# ... 逐条写入所有保留的文件sudosh-cecho ./mysql-bin.000292 /mroldx/data/mysql/data/mysql-bin.index4. 验证并启动主库cat/mroldx/data/mysql/data/mysql-bin.indexdf-h/mroldx/data/mysql/datadockerserviceupdate--forcemysql-master服务名主库成功启动释放约 180GB 空间。第二阶段恢复从库复制从库启动后执行SHOW SLAVE STATUSIO/SQL 线程均为 No。接下来是一连串问题的排查。问题一relay log 元数据损坏ERROR 1872: Slave failed to initialize relay log info structure from the repository原因磁盘满时崩溃导致 relay log 信息不完整。解决STOP SLAVE;RESET SLAVE;STARTSLAVE;问题二GTID 定位失败RESET SLAVE 后Master_Log_File为空IO 线程不知道从哪里开始读取。解决启用 GTID 自动定位STOP SLAVE;CHANGE MASTERTOMASTER_AUTO_POSITION1;STARTSLAVE;问题三主库 binlog 已被清除Cannot replicate because the master purged required binary logs.由于手动删除了主库旧 binlog从库需要的历史 GTID 事务已不存在于主库的 binlog 中。此时有两个选择方案操作风险跳过 GTID 差异RESET MASTERSET GLOBAL gtid_purged可能存在少量数据不一致全量重建mysqldump 导出导入耗时但数据一致性有保障问题四MySQL 8.0 认证问题error 2061 connecting to master replmysql-master:3306MySQL 8.0 默认使用caching_sha2_password复制连接需要 SSL 或公钥交换。解决将复制用户改为兼容认证方式-- 在主库执行ALTERUSERrepl%IDENTIFIEDWITHmysql_native_passwordBY密码;FLUSHPRIVILEGES;问题五数据不一致导致 SQL 线程报错Could not execute Update_rows event on table mroldx-server-job.sj_job_task; Cant find record in sj_job_task, Error_code: 1032从库缺少主库要更新的行记录。临时方案# 从库 my.cnf 临时添加 [mysqld] slave_skip_errors 1032slave_skip_errors 1032表示跳过找不到记录的错误同步追平后应立即去掉此配置。第三阶段全量重建从库最终方案经过多次尝试恢复复制未果最终决定全量重建。1. 主库导出dockerexec$(dockerps-q--filternamemysql-master)bash-c\mysqldump -uroot -p密码 \ --all-databases \ --single-transaction \ --set-gtid-purgedON \ --routines --triggers --events \ /var/lib/mysql/master_full_dump.sql注意重定向写在bash -c内部避免 dump 内容输出到终端。容器内/var/lib/mysql/对应宿主机/mroldx/data/mysql/data/。2. 传输到从库scp/mroldx/data/mysql/data/master_full_dump.sql user从库IP:/mroldx/data/mysql/3. 从库重置并导入STOP SLAVE;RESET SLAVEALL;dockerexec-i$(dockerps-q--filternamemysql-slave)\mysql-uroot-p密码/mroldx/data/mysql/master_full_dump.sql4. 重新配置主从复制CHANGE MASTERTOMASTER_HOSTmysql-master,MASTER_USERrepl,MASTER_PASSWORD密码,MASTER_PORT3306,MASTER_AUTO_POSITION1;STARTSLAVE;SHOWSLAVESTATUS;确认Slave_IO_Running: YesSlave_SQL_Running: Yes恢复完成。根因分析binlog 未配置过期策略 ↓ binlog 无限增长200GB ↓ 磁盘写满 → MySQL 崩溃 ↓ 手动删除 binlog → GTID 链断裂 ↓ 从库无法续接 → 全量重建因素说明根本原因未配置expire_logs_daysbinlog 无限增长扩大因素手动删除 binlog 破坏了 GTID 连续性恢复复杂度增加MySQL 8.0 认证机制变更、relay log 损坏预防措施1. 配置 binlog 自动过期[mysqld] expire_logs_days 7 max_binlog_size 512M2. 磁盘监控告警在 80% 使用率时触发告警留出处理时间窗口。3. 正确清理 binlog 的方式永远不要手动rmbinlog 文件使用 MySQL 命令-- 清理指定日期之前的 binlogPURGEBINARYLOGS BEFORE2026-05-20 00:00:00;-- 清理指定文件之前的 binlogPURGEBINARYLOGSTOmysql-bin.000280;PURGE命令会自动更新索引文件并检查从库是否还依赖这些 binlog。4. 定期验证主从一致性# 使用 Percona Toolkitpt-table-checksum--host主库IP--userroot--password密码 pt-table-sync--print--sync-to-master 从库IP5. 独立备份策略主从不是备份。即使有从库也应该有独立的定时 mysqldump 或 xtrabackup 备份。教训总结不要手动删 binlog 文件—— 用PURGE BINARY LOGS命令它会自动维护索引和检查从库依赖磁盘满时优先恢复主库—— 从库可以重建主库数据不可替代GTID 模式下 RESET SLAVE 要谨慎—— 会丢失位点信息可能导致无法续接MySQL 8.0 的认证机制要注意—— 复制用户建议显式使用mysql_native_password方案 B 失败要果断切方案 A—— 在数据一致性面前时间成本是次要的事前预防远比事后恢复重要—— 一行expire_logs_days 7就能避免这次事故本文基于真实故障恢复过程整理环境为 MySQL 8.0.15 Docker Swarm GTID 复制模式。