不是必须,但对InnoDB表几乎总是要加;不加会锁表导致业务卡顿,加了则利用MVCC快照实现无锁备份。
mysqldump 备份命令必须加 --single-transaction 吗?
不是必须,但对 innodb 表几乎总是要加。不加会导致备份时锁表(flush tables with read lock),业务写入会卡住甚至超时。而 --single-transaction 利用 mvcc 快照,全程不锁表——前提是所有表都是 innodb。
常见错误现象:mysqldump: Got error: 1045: Access denied for user 'backup'@'localhost' (using password: YES),其实是权限不足,不是密码错;或者备份文件大小为 0,常因没加 --skip-lock-tables 又遇到 MyISAM 表导致中断。
- 只备份 InnoDB:必加
--single-transaction,可配--skip-lock-tables(它本身不生效,但能防止 mysqldump 自动降级加锁) - 混有 MyISAM 表:不能用
--single-transaction,得改用--lock-all-tables,但停写窗口变长 - 加
--routines --triggers --events才能完整导出存储过程和事件调度器定义
Cron 时间表达式里 0 2 * * * 真的每天 2 点执行吗?
不一定。Cron 使用系统本地时区,不是 UTC,也不是数据库服务器时区。如果服务器时区是 CST(UTC+8),那确实是每天凌晨 2 点;但如果 DBA 把 MySQL 时区设成 +00:00,而备份脚本里又依赖 NOW() 生成文件名,时间戳就对不上。
更隐蔽的问题:Cron 默认环境变量极简,PATH 通常不含 /usr/local/mysql/bin,直接写 mysqldump 会报 command not found。
- 始终用绝对路径调用:比如
/usr/bin/mysqldump或/opt/mysql/bin/mysqldump - 在 crontab 开头显式声明时区:
CRON_TZ=Asia/Shanghai(systemd cron 支持,传统 vixie-cron 不支持,得靠TZ=Asia/Shanghai) - 在脚本第一行加
#!/bin/bash -l或手动 source profile,确保环境变量加载完整
备份文件命名怎么避免覆盖又方便识别?
用日期时间戳最稳妥,但别只信 $(date +%F)——同一天多次失败重试会覆盖;也别用 $(date +%s),纯数字难肉眼排序。关键是把「实例标识 + 时间粒度 + 压缩状态」都塞进名字里。
容易踩的坑:文件名含空格或冒号(:),在 shell 中未引号包裹直接导致命令截断;或者用 %Y%m%d_%H:%M,冒号会被 shell 当作分隔符解析失败。
- 推荐格式:
mysql_backup_<instance>_$(date +\%Y\%m\%d_\%H\%M\%S).sql.gz(注意转义%和:) - 实例标识建议取自配置:比如从
my.cnf里抽server-id,或用主机名 + 端口,如db-prod-3306 - 加
--set-gtid-purged=OFF(若 GTID 关闭)或(开启时),否则恢复时可能报 <code>GTID_PURGED can only be set when @@GLOBAL.GTID_MODE = ON
备份后不校验、不清理等于没备
自动备份最危险的阶段不是执行,而是执行完没人看结果。一个被磁盘满撑爆的 gzip 进程会让 .sql 文件残留一半,后续 restore 直接报语法错误;而没人删旧备份,三个月后 /backup 分区占满,cron 下次执行直接失败静默。
性能影响常被低估:全库 dump + gzip 在千兆网、机械盘环境下可能持续 20 分钟以上,期间 I/O iowait 拉高,连慢查询日志写入都延迟。
- 加
--compress(客户端压缩)比管道| gzip更省内存,但要求 MySQL 服务端支持 - 用
md5sum校验备份前后一致性(先算源库SELECT MD5(CONCAT(...)) FROM information_schema.tables太重,改用gzip -t验证压缩包完整性更实际) - 清理策略建议保留最近 7 天 + 每月 1 号全量,用
find /backup -name "mysql_backup*.sql.gz" -mtime +7 -delete
真正麻烦的是跨版本恢复:MySQL 5.7 的 mysqldump 输出,在 8.0 上导入可能因 utf8mb4_0900_as_cs 排序规则报错,这时候光有备份文件也没用——得同步记录 mysqldump --version 和目标 MySQL 版本。


















