Navicat 默认备份使用 FLUSH TABLES WITH READ LOCK 全局锁导致业务写入阻塞,应改用 --single-transaction 基于 MVCC 快照实现无锁备份,并排查长事务、binlog 压力及应用一致性误判。
navicat 默认备份会阻塞写操作,业务系统超时不是配置问题,而是锁机制本身在生效。 你看到的“preparing backup…”卡住、接口报 mysql server has gone away 或业务响应变慢,根本原因不是网络或超时设置太短,而是 flush tables with read lock 正在全局阻塞所有 dml——只要备份没完成,insert/update/delete 就会排队等待,积压后触发业务层超时。
为什么 Navicat 备份会锁死业务写入
Navicat 图形化备份底层调用的是 mysqldump --lock-tables(非 InnoDB 表)或默认启用 --lock-all-tables(即使有 InnoDB)。它不区分表引擎,也不自动降级为事务快照。一旦执行 FLUSH TABLES WITH READ LOCK,所有后续写请求都会被挂起,直到 UNLOCK TABLES 执行完毕——这个窗口可能长达数分钟,尤其当库中存在 MyISAM 表、触发器、视图或大表时。
- MyISAM 表强制走表级锁,
--single-transaction对其无效 - 备份过程中若有人执行
ALTER TABLE或长事务未提交,FTWRL会一直等待,业务写入同步卡住 - 从库开启
read_only=ON时,FLUSH TABLES WITH READ LOCK会被拒绝,备份直接失败
绕过锁的实操路径:用 --single-transaction 替代全局锁
这不是“调高超时就能解决”的问题,必须让备份放弃全局读锁,改用 InnoDB 的 MVCC 快照。Navicat 界面不提供该开关,但能通过包装脚本“骗过”它:
- 确认 MySQL 版本 ≥ 5.6,且目标库全为 InnoDB 表(
SHOW TABLE STATUS WHERE Engine != 'InnoDB') - 在 Navicat 连接属性 → 「高级」→ 「MySQL 路径」中,填入你自建的包装脚本路径(不是原
mysqldump) - Windows 下新建
mysqldump.bat,内容为:@%~dp0\mysqldump.exe --single-transaction --set-gtid-purged=OFF %* - Linux/macOS 写 shell 脚本并
chmod +x;把原mysqldump改名(如mysqldump.real),再把包装脚本放同目录 - 备份弹窗中勾选「包含存储过程/函数」「包含事件」——这些选项生成的
--routines --events与--single-transaction兼容
验证是否生效:导出的 SQL 文件开头应含 START TRANSACTION WITH CONSISTENT SNAPSHOT;,而非 FLUSH TABLES WITH READ LOCK;。
备份期间业务仍超时?检查长事务和 binlog 压力
即使启用了 --single-transaction,业务超时仍可能发生——此时问题已不在锁表,而在事务快照开销或 binlog 冲突:
- 备份开始时,InnoDB 需保留所有早于快照时刻的 undo log,若此时存在运行超 10 分钟的事务,undo 区会暴涨,拖慢整个实例 I/O
- 执行
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED;,杀掉TRX_STATE = 'RUNNING'且TRX_STARTED早于当前时间 5 分钟以上的事务 - 如果开启了
binlog_format=ROW且备份期间有大量写入,binlog 写入可能成为瓶颈,观察SHOW GLOBAL STATUS LIKE 'Binlog_cache_use';是否异常高 -
--single-transaction不阻塞写,但会延长事务可见性窗口,某些强一致性业务逻辑(如秒杀扣减)可能因读到旧快照而重试失败
真正麻烦的不是“怎么让备份不卡”,而是“怎么让备份不干扰业务”。--single-transaction 是必要条件,但不是充分条件——它只解决锁表,不解决 undo 压力、binlog 同步延迟、或应用层对实时性的误判。上线前务必在低峰期用真实流量压测,观察监控里的 Innodb_buffer_pool_wait_free 和 Threads_running 是否跳变。


















