必须在mysqldump完成后立即执行md5sum生成校验值并保存为同名.md5文件,恢复前用md5sum -c严格验证,仅显示“backup.sql: ok”才可导入,否则可能因截断、坏道或缓存异常导致中途失败。

备份文件能解压、能导入、甚至没报错,不等于它在灾难时真能用。唯一能暴露权限缺失、字符集错配、GTID 不兼容、binlog 断链等隐藏问题的,是走通一次完整恢复流程。
用 md5sum -c 验证备份文件是否被截断或静默损坏
MySQL 自身不校验写入内容,磁盘坏道、NFS 缓存异常、写入中断都可能导致 backup.sql 看似存在,实则末尾缺失几 KB。这类损坏不会在导入初期报错,而是中途突然语法错误或乱码。
- 必须在
mysqldump完成后 **立刻** 执行:mysqldump -u root db > backup.sql && md5sum backup.sql > backup.sql.md5 -
backup.sql.md5必须和备份文件同目录、同名,且权限设为600(避免被意外覆盖) - 恢复前执行:
md5sum -c backup.sql.md5,只看到backup.sql: OK才可继续;若显示FAILED,立即停手,查df -h是否磁盘满、dmesg | tail是否有 I/O 错误 - 别用
md5sum backup.sql打屏比对——人眼不可靠,也留不下自动验证痕迹
用 gunzip -t 和 zcat | head 快速筛掉损坏压缩包
很多故障卡在第一步:gzip 层已损坏,但没人检查。直接导入只会等到中途报 Invalid or incomplete deflate data 才发现。
-
gunzip -t backup.sql.gz返回 0 表示压缩格式完好;非 0 就别往下试了 - 进一步确认 SQL 可读:
zcat backup.sql.gz | head -n 30 | grep -q "CREATE DATABASE",能匹配上才算“开头合法” - 若报
gzip: stdin: not in gzip format,说明文件根本不是 gzip(可能是传输中断或重命名错误) - 别用
gzip -d全量解压大文件——既慢又占磁盘;-t是无副作用的真轻量校验
恢复到临时库后用 mysqlcheck --check 暴露表结构与权限问题
语法通 ≠ 表结构全。常见漏掉 CREATE TABLE、字段类型被截断、视图 DEFINER 用户不存在等问题,mysqlcheck 能当场暴露。
- 先建空库:
mysql -e "CREATE DATABASE IF NOT EXISTS test_restore" - 再导入:
zcat backup.sql.gz | mysql test_restore(注意别用重定向,避免缓冲区截断) - 立即执行:
mysqlcheck -u root -p --check test_restore,看到test_restore.table_name OK才算过第一关 - 若提示
Table 'xxx' doesn't exist,大概率是备份时加了--no-create-info或mysqldump版本太低漏导了某些表
用 CHECKSUM TABLE 比对关键表数据页哈希而非仅看行数
information_schema.TABLES.table_rows 对 InnoDB 是估算值,偏差可能达 20%;而 CHECKSUM TABLE 计算的是实际数据页哈希,结果一致才说明内容未变。
- 备份前在原库执行:
CHECKSUM TABLE user_config;,记下返回的Checksum值 - 恢复后在
test_restore库执行同样语句,比对值是否完全一致 - 对大表可抽样查主键范围:
SELECT MIN(id), MAX(id), COUNT(*) FROM orders;,两边数值应完全匹配 - 遇到
ERROR 1062 Duplicate entry或中文变????,重点查三处:--default-character-set=utf8mb4是否加了、目标库character_set_database是否一致、SQL 文件开头是否有SET NAMES utf8mb4;
真正难控的不是命令怎么写,而是校验动作和备份动作之间的时间耦合度——你得确保 mysqldump 进程退出后,md5sum 立刻开始读那个文件,中间不能有 shell 调度延迟、IO 队列堆积或 NFS 缓存绕过。这点一旦松动,所有后续校验都建立在沙上。











