mysqldump 必须加 --single-transaction 才能保证 InnoDB 表一致性备份,它通过 REPEATABLE READ 事务快照避免数据错乱,且需搭配 --skip-lock-tables;MyISAM 表仍需全局锁或停写。

mysqldump 命令必须加 --single-transaction 才能保证一致性
InnoDB 表在备份过程中若无事务隔离,可能导出部分已提交、部分未提交的数据,导致恢复后数据错乱。不加该参数时,mysqldump 默认使用 LOCK TABLES,会阻塞写入;而加了 --single-transaction 后,它会在备份开始时启动一个 REPEATABLE READ 事务,整个导出过程看到的是事务快照——这才是生产环境安全备份的前提。
注意:该参数仅对 InnoDB 有效,MyISAM 表仍需加 --lock-all-tables 或停写,否则无法保证一致性。
- 必须搭配
--skip-lock-tables使用(否则--single-transaction会被忽略) - 避免混用
--all-databases和--databases,前者会导出 mysql 系统库,后者只导指定库 - 建议显式指定字符集:
--default-character-set=utf8mb4,防止恢复时报错ERROR 1273 (HY000): Unknown collation
备份脚本里要用 date +\%Y\%m\%d_\%H\%M 控制文件名,别用 \$(date)
直接写 \$(date) 在 shell 脚本中容易因空格或换行符导致后续命令(如 gzip、rm)失败。更严重的是,如果系统 locale 不是 C,date 输出的星期/月份名可能含中文或特殊字符,造成 tar 归档异常或定时任务日志混乱。
- 正确写法:
backup_file="backup_\$(date +\%Y\%m\%d_\%H\%M).sql" - 文件名中避免
:(Windows 不兼容)、空格、中文,否则影响 rsync 或异地同步 - 建议在
mysqldump后立刻检查退出码:if [ \$? -ne 0 ]; then echo "dump failed"; exit 1; fi
crontab 定时执行前,必须用 sudo -u mysql 或配置 ~/.my.cnf
crontab 默认以 root 或指定用户身份运行,但 mysqldump 需要数据库账号密码。硬编码密码在命令行里(如 -p123456)会暴露在 ps aux 中,极不安全;用 -p 交互式输入又会让 cron 卡住。
最稳妥的做法是创建 /root/.my.cnf(权限设为 600),内容如下:
[client] host=localhost user=backup_user password=your_strong_password socket=/var/run/mysqld/mysqld.sock
然后在脚本里直接调用 mysqldump --defaults-extra-file=/root/.my.cnf ...,既免密又不泄密。
- 不要把
.my.cnf放在/etc/my.cnf下——那是全局配置,影响所有 MySQL 客户端行为 - 若 MySQL 监听在非默认 socket 路径,务必在
.my.cnf中显式写socket=...,否则 cron 下连接失败 - 测试 cron 前,先手动切换到对应用户执行一遍脚本:
sudo -u root /path/to/backup.sh
保留最近 7 天备份,用 find /path -name "backup_*.sql.gz" -mtime +7 -delete
自动备份不清理就是磁盘爆满的开始。用 -mtime +7 比用 -ctime 或 -atime 更可靠,因为它基于文件内容修改时间(即备份生成时间),不受 touch 或 rsync 更新时间戳干扰。
- 删除前建议先 dry-run:
find /backup -name "backup_*.sql.gz" -mtime +7 -print - 不要写成
-exec rm {} \;,效率低且易出错;-delete是 find 内置动作,更安全 - 若备份路径有子目录(如按库名分目录),需加
-maxdepth 1防止误删 - 删除操作本身也应记录日志:
find ... -delete >> /var/log/mysql/backup_cleanup.log 2>&1
mysqldump 或 gzip。


















