mysqldump 默认会锁表,目的是通过执行 FLUSH TABLES WITH READ LOCK 来确保备份过程中的数据一致性。对于纯 InnoDB 数据库,通常可以配合 --single-transaction 和 --quick 参数实现备份时不锁表;但如果库中存在 MyISAM 表,mysqldump 就可能自动退回到全局读锁模式,这本质上取决于存储引擎本身的锁机制。

mysqldump 默认会锁表,但是否必须锁表,取决于表的存储引擎、备份方案以及你对数据一致性的要求——关键不只是“要不要锁”,更在于“能否不锁表”以及“不锁表是否会造成数据不一致”。
为什么 mysqldump 默认锁表?
因为它的默认行为通常会依赖 FLUSH TABLES WITH READ LOCK(FTWRL)来加全局读锁,从而保证备份时所有表处于同一个逻辑时间点。这种方式对 MyISAM 表来说是最可靠、也是最常见的做法;但对于支持事务的 InnoDB 表,往往还有更合适的无锁备份方式可选。
--single-transaction 能否替代锁表?
可以,但必须满足以下前提条件:
--single-transaction只对InnoDB表有效;如果数据库中包含MyISAM表,就可能无法实现真正意义上的无锁一致性备份,通常会退化为依赖 FTWRL- 需要确保
autocommit=1,否则事务快照可能无法按预期完成提交 - 备份期间应避免任何 DDL 操作,例如
ALTER TABLE、DROP TABLE等,因为隐式提交可能破坏一致性快照 - 不能与
--lock-tables或--lock-all-tables同时使用,否则会直接报错
常见且相对安全的命令示例:mysqldump --single-transaction --routines --triggers -u root -p mydb > backup.sql
系统库(mysql)备份为何总卡住?
如果直接执行 mysqldump mysql,有时会出现卡住、无响应,或者报出 ERROR 1142 的情况。这通常是因为权限相关表不支持常规的 LOCK TABLES 操作。此时应显式加上 --skip-lock-tables 参数,并且不能依赖 --single-transaction(因为它对系统库场景并不适用)。
正确示例:mysqldump --skip-lock-tables -u root -p mysql user db host > mysql_privileges.sql
另外要注意:执行备份的账号必须在 mysql.* 上具备 SELECT 权限,通常建议使用 root 或专门授权的备份账号。
大表或混合引擎怎么办?
如果单表规模超过 100GB,或者数据库中同时包含 MyISAM 与 InnoDB 混合引擎,那么 mysqldump 往往就不是最理想的 MySQL 备份方案:
mysqldump属于逻辑备份,恢复速度通常较慢、CPU 开销较高,而且在未使用--quick时还可能因结果集过大导致内存占用过高甚至溢出- MyISAM 表无法彻底绕过锁表,只能尽量放在从库执行备份,并且需要先
STOP SLA VE并记录Exec_Master_Log_Pos - 在生产环境、高并发业务或对在线影响敏感的场景下,更建议优先考虑
Percona XtraBackup,它通过复制数据文件和 redo log 实现更接近真正不锁表的热备份
不要被“--lock-tables=false”这个参数表面含义误导:它只是跳过锁表动作,并不能保证备份数据的一致性,因此更适合测试环境,或能够接受脏读、数据轻微偏差的离线场景。
ENGINE(例如使用 SHOW CREATE TABLE tbl),往往比单纯记忆参数组合更重要。