必须用管道流式加密,因先dump再加密会产生明文窗口期,backup.sql可能被ps、日志、缓存、swap或云代理捕获,且异常退出时残留磁盘;推荐mysqldump | gzip | openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -salt流式加密,禁用-k参数,恢复时须流式解密导入。

MySQL逻辑备份文件(即mysqldump输出的SQL)本身是明文,不加密等于把表结构、字段值、注释甚至密码哈希全摊在磁盘上。必须用管道流式加密,且不能依赖事后补救。
为什么不能先 dump 再加密
常见错误是执行mysqldump -u root -p db > backup.sql,再跑gpg -c backup.sql。这中间存在明文窗口期:backup.sql可能被ps aux、审计日志、容器层缓存、临时文件扫描工具捕获;若脚本异常退出,文件还残留磁盘——shred -u也未必能彻底擦除SSD上的旧块。
- Linux内核/容器运行时可能将该文件页缓存到内存或swap
- 某些云平台备份代理会自动扫描新创建的
.sql文件 -
bash_history和/proc/PID/cmdline里也可能泄露参数(尤其当用了-p'password')
推荐组合:mysqldump + gzip + openssl(最通用)
openssl比gpg更易跨环境部署(多数服务器预装),且-pbkdf2 -iter 1000000能有效防暴力破解。但注意OpenSSL版本兼容性:1.1.1+才支持-pbkdf2,旧版默认弱密钥派生,解密会失败。
- 命令示例:
mysqldump --single-transaction -u backup_user --login-path=local_backup mydb | gzip | openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -salt -out mydb_$(date +%Y%m%d).sql.gz.enc -
--single-transaction对InnoDB保证一致性;MyISAM必须换--lock-all-tables - 务必加
-salt和-iter 1000000,否则老版本OpenSSL生成的密文无法被新版本解密 - 别用
-k传密钥——它做MD5哈希且无salt,极不安全
恢复时必须流式解密导入,禁用临时文件
看到gpg -d file.gpg > tmp.sql && mysql -u root -p mydb 这种写法要立刻停手。tmp.sql可能被未授权进程读取,崩溃时还可能残留明文。
- 正确做法:
openssl enc -d -aes-256-cbc -pbkdf2 -iter 1000000 -in mydb.sql.gz.enc | gunzip | mysql -u root -p mydb - 解密输出必须是UTF-8无BOM,否则
mysql报ERROR 1064;若原始dump含BOM,需在mysqldump加--result-file并用iconv预处理(不推荐,应从源头避免) - 如果提示
bad decrypt,不是密码错就是算法/迭代数不匹配——openssl不会明确告诉你哪错了,得靠对比备份时用的参数
密钥管理比算法选择更重要
AES256-CBC再强,私钥或密码丢了,备份就等于报废。生产环境严禁硬编码密码,也不该把GPG私钥放在备份服务器上。
- 密码类密钥:用
gpg --batch --passphrase-fd 0从安全管道注入,或对接HashiCorp Vault/KMS动态拉取 - GPG公钥方案:所有DB节点只存公钥,私钥独存于离线恢复机;导入前确认
gpg --list-keys显示状态为[SC](签名+认证) - 定期轮换密码:不是改一次就完事,要同步更新所有备份脚本引用,并验证旧密文仍可解密
真正卡住恢复的从来不是加密算法,而是密钥放错了位置、用了已弃用的AES128、或者解密命令漏了-iter参数——这些细节在自动化脚本里极易被忽略,必须每次备份后实测还原流程。


















