mysqldump + gzip 管道压缩备份需加 --single-transaction 或 --lock-all-tables 保证一致性,避免空文件;加密推荐 openssl -pbkdf2 -iter 1000000 或 gpg 公钥方案;须校验、清理并定期实测恢复。

mysqldump + gzip 一次性压缩备份
直接用管道把 mysqldump 输出喂给 gzip,避免生成中间大文件,省空间也省时间。注意别漏掉 --single-transaction(对 InnoDB 表)或 --lock-all-tables(对 MyISAM),否则可能备份出不一致数据。
常见错误是忘记加 -h、-u、-p 参数导致连接失败,或者导出时没指定库名,结果空文件还看不出错。
mysqldump -h localhost -u root -p --single-transaction --routines --triggers mydb | gzip > mydb_$(date +%Y%m%d).sql.gz- 如果密码不想明文出现在命令行,改用配置文件:
~/.my.cnf写好[client]段,再加--defaults-extra-file=~/.my.cnf - 大库慎用默认的
gzip级别(6),可加-9压得更小,但 CPU 占用翻倍;小库用-1更快
用 openssl 对备份文件加密(AES-256-CBC)
gzip 后的文件用 openssl enc 加密最通用,解密方只要有 OpenSSL 就能还原。别用 -k 直接传密码——它会做弱哈希,且无法控制 salt;必须用 -pbkdf2 -iter 1000000 提高暴力破解成本。
加密后文件无法用常规文本工具查看,但也不会报错;误输密码解密时,openssl 会输出乱码或报 bad decrypt,不是“解密失败”提示,容易误判成功。
- 加密:
mysqldump -u root -p mydb | gzip | openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -salt -out mydb.enc
- 解密:
openssl enc -d -aes-256-cbc -pbkdf2 -iter 1000000 -in mydb.enc | gunzip | mysql -u root -p mydb
- 若要分步操作(比如先存 .sql.gz 再加密),记得用
-md sha256显式指定摘要算法,老版本 OpenSSL 默认用 md5,新旧不兼容
用 gpg 替代 openssl 实现密钥对加密
适合团队协作场景:用公钥加密,私钥解密,不用共享密码。前提是所有备份发起方都导入了同一个公钥(gpg --import public.key),且私钥在恢复机器上可用。
gpg 默认压缩+加密一体完成,但要注意:--compress-algo 在新版 GnuPG 中已弃用,改用 --compress-level;另外,--cipher-algo AES256 必须显式指定,否则可能 fallback 到较弱算法。
- 加密:
mysqldump -u root -p mydb | gpg --encrypt --recipient 'backup@team.com' --cipher-algo AES256 --compress-level 9 > mydb.gpg
- 解密:
gpg --decrypt mydb.gpg | mysql -u root -p mydb
- 若私钥有密码,每次解密都会交互输入;可临时用
gpg-agent缓存,但生产环境别设永不过期
备份脚本中校验与清理的关键点
自动备份脚本里最容易被忽略的是校验和与过期清理。只生成文件不验证,等真要恢复时才发现损坏,就晚了。gzip 文件用 gzip -t,gpg 用 gpg --verify(需提前签名),openssl 加密文件没法直接校验,只能靠解密后 head -c 100 看是否含 SQL 头(如 CREATE DATABASE)。
清理策略不能只看天数,还要防磁盘写满。建议用 find 配合 -mmin 或 -mtime,但注意 NFS 挂载点可能不支持精确时间戳。
- 校验 gzip:
gzip -t mydb_20240501.sql.gz && echo "OK" || echo "Corrupted"
- 清理 7 天前的 .sql.gz:
find /backup -name "*.sql.gz" -mtime +7 -delete - 加锁防止并发备份冲突:
flock -n /tmp/backup.lock -c "mysqldump ... | gzip > ...",没抢到锁就直接退出,别硬等
Unknown character set: 'utf8mb4' 这种细节上。










