必须加--single-transaction(innodb)或--lock-all-tables(myisam),并搭配--routines--triggers--events、--default-character-set=utf8mb4,密码通过~/.my.cnf(chmod 600)或mysql_pwd安全传入,脚本需设path、用绝对路径、写全备份路径、重定向stderr,文件按日期命名并用find清理。

mysql dump 命令怎么写才不丢数据
直接用 mysqldump 默认参数备份,很可能漏掉视图、存储过程、触发器,甚至在有长事务时导致备份不一致。关键不是“能不能导出”,而是“导出的能不能原样恢复”。
- 必须加
--single-transaction(InnoDB 表适用),避免锁表又保证一致性;MyISAM 表得用--lock-all-tables,别混用 - 加上
--routines --triggers --events,否则存储过程和事件不会进备份文件 - 显式指定字符集,比如
--default-character-set=utf8mb4,防止乱码或导入失败 - 不要省略
-h、-P、-u、-p参数——尤其是-p后面**不要直接跟密码**(会暴露在进程列表里),改用配置文件或MYSQL_PWD环境变量
shell 脚本里怎么安全存数据库密码
把密码写死在脚本里等于公开给所有能看 ps aux 的人。Linux 下最稳妥的方式是用 MySQL 的 ~/.my.cnf 配置文件,但权限必须设成 600,否则 mysqldump 会拒绝读取。
- 创建
~/.my.cnf,内容:[client] host=localhost user=backup_user password=your_real_password port=3306
- 立刻执行
chmod 600 ~/.my.cnf,否则脚本运行时会报错:Warning: World-writable config file '/home/user/.my.cnf' is ignored - 脚本里调用就简化为:
mysqldump --single-transaction --routines db_name > backup.sql,不用再传用户密码 - 如果必须用环境变量(比如容器场景),用
MYSQL_PWD=xxx mysqldump ...,但确保该变量不在历史记录或日志中输出
cron 执行备份脚本为什么总失败
cron 环境非常干净:没有你的 shell profile、没有 PATH、没有当前工作目录保障。脚本在终端能跑,放进 crontab 就报 command not found 或 No such file or directory 是常态。
- 在脚本开头强制设置环境:
PATH=/usr/local/bin:/usr/bin:/bin,或者所有命令都写绝对路径,比如用/usr/bin/mysqldump而不是mysqldump - 用绝对路径写备份文件目标,比如
/backup/db_$(date +\%F).sql,别用./backup/—— cron 的 cwd 是用户 home,不一定存在该子目录 - 重定向 stderr 到日志:
2>> /var/log/backup.log,否则失败了你也看不到错误 - 测试 cron 环境:临时加一行
* * * * * env > /tmp/cron_env.txt,对比你手动执行env的输出,差在哪就补哪
备份文件怎么命名和清理才不撑爆磁盘
每天一个全量备份,不删旧文件,三个月后磁盘告警是必然的。但只留最近 7 天又可能错过关键恢复点——得按保留策略分层处理。
- 文件名带日期和时间:
db_prod_$(date +\%Y\%m\%d_\%H\%M).sql,避免空格和冒号(cron 解析会出问题) - 用
find定期清理:比如保留 7 天内文件,加到脚本末尾:find /backup -name "db_prod_*.sql" -mtime +7 -delete - 压缩备份文件节省空间:
gzip $backup_file,但注意:恢复时得先gunzip,别忘了在恢复文档里写清楚 - 更稳的做法是每天只保留一个全量 + binlog 增量归档,但那是另一套逻辑,先确保全量不丢再说
实际跑起来最常卡在密码权限和 cron 环境上,这两个点没调通,后面所有逻辑都白搭。备份脚本不是写完就能放心的,得看三次:手动跑一次、加到 cron 跑一次、隔天检查日志一次。











