mysqldump管道gzip更安全因避免临时文件,但需防进程失败残留损坏包;应加--single-transaction、用gzip -c -v、命名含时间戳与库名、绝对路径、备份后立即gunzip -t校验并启用set -o pipefail。

mysqldump 直接管道进 gzip 为什么更安全
因为不落地临时文件,避免磁盘写满或权限问题,也省去手动清理步骤。但要注意 mysqldump 进程失败时,gzip 可能还在跑,残留空文件或损坏压缩包。
实操建议:
- 始终加
--single-transaction(InnoDB)或--lock-tables=false(MyISAM),否则管道卡住会导致备份中断且无提示 - 用
gzip -c而不是gzip,确保输出到 stdout,不尝试改名或覆盖 - 加上
-v参数给mysqldump,看到表名输出才说明连接和权限正常;没输出就停在第一张表,大概率是锁表失败或权限不足 - 示例命令:
mysqldump -u root -p --single-transaction mydb | gzip -c > mydb_$(date +%F).sql.gz
gzip 压缩级别对备份耗时和体积的真实影响
默认 gzip 是 -6 级,-9 并不总值得:CPU 占用翻倍,体积只少 3%~5%,而备份窗口紧张时可能超时。
实操建议:
- 线上定时备份统一用
gzip -1或gzip -3,快、稳、解压兼容性好(老系统gunzip对高版本压缩格式偶有报错) - 归档冷备可跑一次
gzip -9,但别在生产机上干——它会吃光 CPU,拖慢mysqld - 别用
pigz替代gzip除非确认目标机器装了它,否则恢复时gunzip解不开pigz产出的并行流
备份文件名里必须包含时间戳和数据库名
没有时间戳的 backup.sql.gz 在 cron 里跑三次后就覆盖两次,出事根本不知道该还原哪份;不带库名则多个库备份混在一起,恢复时搞错对象。
实操建议:
- 用
$(date +\%Y\%m\%d_\%H\%M)而不是%F,避免日志名撞车(%F不含时分,同天多次备份会覆盖) - 数据库名从
mysqldump参数里取,别硬编码;脚本里用变量DB_NAME="myapp_prod",然后拼成${DB_NAME}_$(date +\%Y\%m\%d_\%H\%M).sql.gz - 路径别写相对路径,
~/backups/在 cron 下常指向 root 家目录,应写绝对路径如/data/backups/
gzip 流中断导致文件不可解压怎么快速识别
gunzip -t xxx.sql.gz 报 unexpected end of file 就是流被截断,常见于网络中断、磁盘满、mysqldump 被 kill,但 gzip 还在写头。
实操建议:
- 每次备份完立刻跑
gunzip -t,失败就删掉并告警——别等恢复时才发现 - 加
set -o pipefail到 shell 脚本开头,否则管道中任意命令失败,整个命令仍返回 0,cron 看不出异常 - 用
stat -c "%s" file.sql.gz粗筛:小于 1KB 的基本是空包或中断包(除非库真就一张空表)
gunzip -t 校验和 pipefail 开关——它们不增加功能,但决定了你凌晨三点能不能放心睡。


















