生产环境mysqldump全量备份必须加--single-transaction,否则默认启用--lock-tables导致全局读锁阻塞写入;该参数利用innodb的mvcc机制在repeatable read隔离级别下创建一致性快照,全程无锁,但要求全库为innodb且备份中禁止ddl操作。

mysqldump 全量备份在生产环境必须加 --single-transaction,否则会锁表阻塞业务写入。InnoDB 引擎下不加这个参数,默认行为是 --lock-tables,线上绝对禁用。
为什么必须用 --single-transaction
它利用 InnoDB 的 MVCC 快照机制,在备份开始时建立一致性视图,全程不锁表,业务读写不受影响。但前提是:所有表必须是 InnoDB;不能有 DDL 操作(如 ALTER TABLE)穿插在备份过程中,否则快照可能失效。
常见错误现象:mysqldump: Got error: 1205: Deadlock found when trying to get lock 或备份中途卡住、连接超时——大概率是漏了 --single-transaction,或混用了 MyISAM 表。
- MyISAM 表无法使用该参数,必须改用
--lock-all-tables(停写),所以生产库应统一用 InnoDB - 若误加
--lock-tables,备份期间所有 INSERT/UPDATE/DELETE 都会被阻塞,监控上会看到大量Waiting for table metadata lock -
--single-transaction和--master-data=2可共存,后者还能顺带记录 binlog 位置,方便后续增量恢复
全量备份命令怎么写才安全
生产推荐组合:带结构+数据+routine+event+自动建库语句+压缩,一句话搞定:
mysqldump -uroot -p --single-transaction --routines --triggers --events --databases shop_db | gzip > shop_full_$(date +%Y%m%d_%H%M%S).sql.gz
说明:
-
--databases是关键:生成的 SQL 文件里自带CREATE DATABASE和USE,还原时不用手动建库 - 去掉
--databases直接跟库名(如mysqldump ... shop_db),则还原时必须先CREATE DATABASE shop_db - 压缩不是可选,是必须:一个中等规模库(5–10 GB 数据)未压缩备份可能占 2 倍磁盘空间,且传输慢、IO 压力大
- 时间戳命名(
$(date +...))避免覆盖,也便于按时间筛选保留策略
备份后立刻要验证的三件事
备份文件不是“生成了就完事”,很多故障源于备份无效却没被发现:
- 检查文件是否为空:
gzip -t shop_full_20260928_150000.sql.gz(返回 0 才代表压缩包完整) - 抽样看前 20 行是否有建库和建表语句:
zcat shop_full_20260928_150000.sql.gz | head -20,确认含CREATE DATABASE `shop_db` - 在测试库快速试还原(哪怕只导入一张小表):
zcat shop_full_*.sql.gz | mysql -uroot -p -D shop_db -e "SELECT COUNT(*) FROM user LIMIT 1"
跳过验证等于没备份。定期恢复演练不是“可做可不做”,而是上线前必须纳入运维 checklist。
容易被忽略的权限与字符集问题
备份失败常卡在权限或乱码,不是命令写错,而是环境没配齐:
- 执行用户至少要有:
SELECT(读数据)、LOCK TABLES(即使不用也会检查)、SHOW VIEW(如有视图)、TRIGGER、EVENT、ROUTINE;全库备份还要RELOAD(用于--master-data) - 字符集不一致会导致还原后中文变问号,务必显式指定:
--default-character-set=utf8mb4,尤其 MySQL 8.0 默认用 utf8mb4,而旧备份脚本可能还写 utf8 -
max_allowed_packet太小会导致大表导出中断,建议 mysqldump 启动时加--max-allowed-packet=512M(需与服务端配置匹配)
真正麻烦的从来不是“怎么备份”,而是“为什么备份成功了却恢复不了”——绝大多数都栽在权限、字符集、空文件这三点上。











