正确做法是用管道直连:mysqldump | openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -salt -out backup.sql.enc,避免明文临时文件;解密须先验证再导入,且需注意OpenSSL版本兼容性。

mysqldump 输出直接用 openssl 加密,别先写文件再加密
加密备份的核心是避免明文临时文件泄露,mysqldump 的输出流可以直接交给 openssl 处理。常见错误是分两步:先 mysqldump > backup.sql,再 openssl enc -aes-256-cbc -in backup.sql -out backup.sql.enc——这中间的 backup.sql 会以明文躺在磁盘上,权限稍有疏忽就可能被读取。
正确做法是管道直连:
mysqldump -u root -p'password' --databases db1 db2 | openssl enc -aes-256-cbc -pbkdf2 -iter 100000 -salt -out backup.sql.enc
-
-pbkdf2和-iter 100000是必须加的,否则默认用过时的 EVP_BytesToKey,密钥派生强度极低 -
-salt必须存在,不加会导致相同密码每次生成相同密文,削弱安全性 - 密码由
openssl交互式提示输入,不建议用-pass pass:xxx写死在命令里(会进 shell 历史、进程列表)
解密后不能直接 pipe 给 mysql,得先确认解密完整性
很多人想一步到位:openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -in backup.sql.enc | mysql -u root -p,但一旦解密失败(比如输错密码、文件损坏),mysql 会收到乱码 SQL 并报一堆语法错误,根本看不出是解密环节出的问题。
稳妥做法是先解密到内存或临时文件并验证:
openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -in backup.sql.enc | head -n 5
- 如果能看到类似
-- MySQL dump 10.13或CREATE DATABASE这类有效 SQL 开头,说明解密成功 - 如果报
bad decrypt或输出乱码,立刻停手,别硬塞给mysql - 生产环境恢复前,建议用
openssl enc -d ... | mysql --dry-run(需 MySQL 8.0.27+ 支持)或先导入到测试库
备份时跳过敏感表或字段,光靠加密不够
加密只是传输/存储层防护,如果备份里包含用户密码哈希、身份证号、API 密钥等,哪怕加密了,一旦密钥泄露,所有数据仍裸奔。更合理的做法是在 mysqldump 阶段就过滤。
- 用
--ignore-table=db.table_name跳过整张表(如日志表、审计表) - 对含敏感字段的表,改用
SELECT ... INTO OUTFILE+WHERE条件导出脱敏数据,再加密 - 注意:
mysqldump --where="1=0"不是清空,而是导出空结构;真正要排除数据得用应用层逻辑或触发器拦截
openssl 版本差异直接影响解密兼容性
OpenSSL 1.1.1 和 3.0 对 -pbkdf2 的默认摘要算法不同(前者用 sha256,后者用 sha256 但参数解析更严格),同一命令在不同系统上可能解密失败。
- 显式指定摘要算法可规避:
-md sha256(1.1.1+ 和 3.0 都支持) - 检查当前版本:
openssl version,若为 3.0+,避免用-k(已被弃用),坚持用-pbkdf2+-iter - 跨服务器恢复前,务必在目标机上用小样本验证解密流程是否通路
加密不是加个 pipe 就完事,密钥管理、解密验证、版本对齐,每一步漏掉都可能让备份变成“看起来安全的废纸”。


















