--single-transaction 用于 InnoDB 表一致性无锁备份,通过 REPEATABLE READ 事务获取时间点快照;仅对 InnoDB 有效,MyISAM 仍会锁表;需配合 --all-databases 或库名使用,不适用于单表;长事务可能阻塞 dump。

mysqldump 备份时加 --single-transaction 有什么用
对 InnoDB 表做一致性备份时,--single-transaction 是关键参数。它通过在导出开始时启动一个 REPEATABLE READ 事务,确保整个 dump 过程看到的是同一时间点的数据快照,避免锁表又不丢一致性。
常见错误是没加这个参数却以为“没锁表就安全”——其实 mysqldump 默认会执行 FLUSH TABLES WITH READ LOCK(需 SUPER 权限),导致写入阻塞。而加了 --single-transaction 后,只要表全是 InnoDB,就完全不锁表。
- 仅对 InnoDB 有效;MyISAM 表仍会触发全局只读锁
- 必须搭配
--all-databases或指定库名使用,不能单独用在单表上还指望事务生效 - 如果备份期间有长事务运行,可能导致 dump 等待或失败,注意监控
INFORMATION_SCHEMA.INNODB_TRX
恢复时遇到 ERROR 1046 (3D000): No database selected
这是最常见的恢复失败提示,本质是 SQL 文件里没有 USE `db_name`; 语句,或者你用 mysql 命令时没指定目标库。
正确做法分两种场景:
- 备份的是单个库(如
mysqldump myapp > backup.sql):恢复时必须显式指定库名:mysql myapp < backup.sql
- 备份含
--databases(如mysqldump --databases myapp > backup.sql):SQL 文件开头有CREATE DATABASE IF NOT EXISTS `myapp`;和USE `myapp`;,此时可直接执行:mysql < backup.sql
,但要求目标实例上该库尚不存在,否则会报错重复创建
别用 mysql -e "source backup.sql",这种写法不会自动识别 USE 切库指令。
跳过某些表或忽略特定错误继续恢复
生产环境恢复常遇到表结构不一致、AUTO_INCREMENT 冲突或已存在数据的问题。硬扛着报错中断不如主动控制流程。
mysqldump 备份阶段可用 --ignore-table=db_name.table_name 排除个别大表(比如日志表);恢复阶段则靠 mysql 的容错参数:
-
--force:遇到 SQL 错误(如主键冲突、字段类型不匹配)打印警告但继续执行 -
--init-command="SET FOREIGN_KEY_CHECKS=0;":关闭外键检查,避免因父表未导入导致子表建表失败 - 组合使用更稳妥:
mysql --force --init-command="SET FOREIGN_KEY_CHECKS=0;" myapp < backup.sql
注意:--force 不会跳过语法错误,只跳过运行时约束类错误;且它不记录哪些语句被跳过,建议先用 mysql --verbose 测试一遍。
备份文件过大时的分卷与压缩处理
直接生成几百 MB 甚至 GB 级的 SQL 文件,不仅传输慢、编辑难,导入时还容易因超时或内存溢出失败。
推荐边 dump 边压缩,避免中间落盘大文件:
mysqldump --single-transaction --routines --triggers myapp | gzip > myapp_$(date +%F).sql.gz
恢复时解压直通:
zcat myapp_2024-06-15.sql.gz | mysql myapp
若需按表拆分,不用等 dump 完再切,而是用 --databases + 循环遍历:
for db in $(mysql -Nse "SHOW DATABASES WHERE \`Database\` NOT IN ('information_schema','mysql','performance_schema','sys')"); do
mysqldump --single-transaction "$db" | gzip > "${db}_$(date +%F).sql.gz"
done
这种模式下每个库独立压缩,后续恢复更灵活,也方便并行导入。
真正麻烦的是字符集混用:如果源库用 utf8mb4,而目标 MySQL 配置里 character_set_server 是 latin1,即使加了 --default-character-set=utf8mb4,也可能在恢复时出现乱码或截断。务必确认两端的 collation_connection 和 character_set_client 一致。










