mysqldump 备份必须加 --single-transaction 保证 innodb 一致性且不锁表,文件名需含时间戳并 gzip -1 压缩,密码须用 chmod 600 的 ~/.my.cnf 配置,账号仅授 select/lock tables/show view/trigger 权限,并添加日志、校验与自动清理。

mysqldump 命令必须加 --single-transaction 才能避免锁表
不加这个参数,mysqldump 在备份期间会锁住所有正在读写的表,线上服务可能卡顿甚至超时。尤其在有长事务或大表的场景下,--single-transaction 用 MVCC 快照保证一致性,且不影响写入。
- 仅对 InnoDB 表有效,MyISAM 表仍会加全局读锁,必须搭配
--lock-tables=false(但不推荐 MyISAM 环境做自动备份) - 如果数据库里混用引擎,建议先查
SELECT table_schema, engine FROM information_schema.tables WHERE table_schema NOT IN ('mysql','information_schema','performance_schema'); - 不要用
--all-databases直接备份——它会把系统库也 dump 进去,恢复时容易覆盖权限表,出问题很难回退
备份文件名要带时间戳和压缩,否则 cron 脚本会覆盖旧备份
常见错误是写成 mysqldump ... > backup.sql,第二天再跑就没了。必须用 date 动态生成文件名,并立刻 gzip,不然几百 MB 的 SQL 文件几天就占满磁盘。
- 推荐格式:
backup_$(date +\%Y\%m\%d_\%H\%M).sql.gz(注意\%要转义,否则 shell 解析失败) - gzip 建议加
-1参数:mysqldump ... | gzip -1 > $filename,压缩快、CPU 占用低,比默认级别更适合定时任务 - 别忘了加
2>/dev/null抑制mysqldump: Got error: 1045这类报错输出——否则 cron 会每小时发一封失败邮件
密码不能硬编码在脚本里,要用 ~/.my.cnf 配置文件
写 --password=xxx 或 -p'xxx' 是严重安全隐患:ps 可见、bash history 记录、/proc/$pid/cmdline 暴露明文密码。MySQL 官方明确要求用配置文件方式。
-
~/.my.cnf内容示例:[client] host=localhost user=backup_user password=your_strong_password socket=/var/run/mysqld/mysqld.sock
(注意chmod 600 ~/.my.cnf,否则mysqldump拒绝读取) - 账号最小权限只需:
GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER ON *.* TO 'backup_user'@'localhost'; - 如果 MySQL 启用了
skip-name-resolve,host必须写127.0.0.1或localhost(二者行为不同:localhost 走 socket,127.0.0.1 走 TCP)
crontab 时间设置要避开业务高峰,且必须加日志和保留策略
凌晨 2 点跑备份看似合理,但如果 DBA 同时在做优化或迁移,IO 冲突会导致备份失败或变慢。更麻烦的是没人检查日志,某天磁盘写满、网络挂了、权限失效,备份静默失败好几周都发现不了。
- crontab 示例:
30 1 * * * /path/to/backup.sh >> /var/log/mysql-backup.log 2>&1(固定时间点 + 全量日志) - 脚本末尾加清理逻辑:
find /backup/path -name "backup_*.sql.gz" -mtime +7 -delete,防止堆积 - 加一句校验:
gunzip -t "$filename" >/dev/null 2>&1 || { echo "Corrupted backup: $filename"; exit 1; },至少确认 gzip 没损坏
真正难的不是写完脚本,而是让备份在各种异常下(磁盘满、连接断、权限变、MySQL 重启)依然可追溯、可报警、可恢复。每次改完记得手动执行一遍,看日志、看文件、解压一条记录验证。











