最可靠方式是用docker run启动预置损坏的mysql 5.7容器,因其可秒级重置状态、目录权限与线上一致且能主动触发物理/逻辑/日志层故障;本地多实例和mysql sandbox均无法精准模拟ibdata1损坏或frm丢失等典型生产故障。

直接用 docker run 启一个预置损坏数据的 MySQL 5.7 容器,是目前最可靠、最贴近真实故障场景的备份恢复演练环境搭建方式。
为什么不用本地多实例或 MySQL Sandbox?
本地多实例要手动删 datadir、清 socket、处理文件权限,稍有遗漏就复用旧状态;MySQL Sandbox 默认不支持指定 mysql:5.7.30 镜像,且生成实例默认开启 innodb_file_per_table=ON,无法模拟 ibdata1 损坏或 .frm 文件丢失这类典型生产故障。
真正需要的是:状态可秒级重置、目录结构和权限与线上一致、能主动触发各类损坏。Docker 天然满足这三点。
docker run 命令必须带的关键挂载项
这条命令不是“跑起来就行”,而是为恢复演练定制的:
docker run --rm -d \ --name mysql57-dirty \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3307:3306 \ -v $(pwd)/mysql57-data:/var/lib/mysql \ -v $(pwd)/my.cnf:/etc/my.cnf \ -v /dev/null:/var/log/mysql/error.log \ mysql:5.7.30
-
-v $(pwd)/my.cnf:/etc/my.cnf必须挂载自定义配置,确保含innodb_file_per_table=OFF、log_bin=ON、server-id=1—— 否则没法练 binlog 恢复或共享表空间恢复 -
-v /dev/null:/var/log/mysql/error.log是故意的:让错误日志不可写,方便触发“磁盘满”类故障(比如ERROR 3写日志失败) - 绝不能把
--rm和-v /dev/null:/var/lib/mysql组合使用 —— 那样一启动数据就空了,没得可恢复
首次启动后必须手动预置的三类损坏样本
只靠 SQL 报错不够,恢复演练必须覆盖物理层、逻辑层、日志层。进容器后立刻执行:
mysql -uroot -p123456 -e "CREATE DATABASE recover_test; USE recover_test; CREATE TABLE t1(id INT); INSERT INTO t1 VALUES(1),(2),(3);"
再手动破坏:
-
frm + ibd 丢失:执行rm -f /var/lib/mysql/recover_test/t1.frm /var/lib/mysql/recover_test/t1.ibd,保留ibdata1—— 测试mysqld启动失败或表不可见场景 -
binlog 截断:用mysqlbinlog找到某 position,然后mysqlbinlog --stop-position=XXX mysql-bin.000001 > partial.sql,再删掉原 binlog 文件 —— 模拟归档丢失 -
error.log 不可写 + datadir 权限异常:执行chmod 000 /var/log/mysql/和chown nobody:nobody /var/lib/mysql—— 触发启动报错The server quit without updating PID file
复杂点在于:每种损坏都要对应不同恢复路径(mysqldump 导入、mysqlbinlog 回放、xtrabackup --prepare、甚至手工修复 ibdata1),而容器每次 docker rm -f 后重建,才能保证下一次演练不被上次残留状态干扰。











