关闭「在事务中运行」可缓解内存溢出,因其将大事务拆为小批次提交;但根本原因是navicat解析sql、缓存结果集及维持连接状态的整套行为,需配合调小fetch size、禁用日志缓存等措施,并优先使用命令行或load data infile替代。
直接关掉「在事务中运行」能立刻缓解内存溢出,但不是万能解法——它只是把单次大事务拆成小批次提交,真正撑爆内存的往往是 navicat 自身解析 sql 文件、缓存结果集、维持连接状态的整套行为。
为什么「在事务中运行」一开就崩
Navicat 默认勾选该选项时,会把整个 .sql 文件所有语句包进一个事务。这意味着:每条 INSERT 都要生成 undo 记录、维护锁状态、缓存回滚日志,全部堆在内存里不释放。几百万行脚本进来,History list length 瞬间飙到 10 万+,MySQL 服务端和 Navicat 客户端双线程吃光内存。
- 这个选项只出现在「运行 SQL 文件」对话框里,路径是:右键数据库 →「运行 SQL 文件…」→ 选文件后点「高级」→ 取消勾选
在事务中运行 - 它不在「导入向导」或「数据传输」界面出现,别找错地方
- 关闭后,Navicat 改为默认每 1000 行左右自动提交一次(具体值不可调),峰值内存下降 60% 以上
关事务后还崩?检查 Fetch Size 和日志缓存
自动任务或后台导入更容易 OOM,因为 Navicat 不会像手动操作那样“喘口气”——它默默加载全部结果、缓存 AST、维持连接元数据快照,直到内存耗尽。
- 打开任务编辑页 →「高级」选项卡 → 取消勾选
记录详细日志和保存执行结果 - 对「数据传输」类任务,在「选项」里把
Fetch Size显式设为500(默认为 0 表示全取) - 禁用
启用查询分析器——它后台持续收集执行计划,是长周期任务的内存黑洞
比关事务更稳的三招替代方案
当数据量超 500MB 或 1000 万行,光靠客户端调参已不够。本质问题是 Navicat 不是 ETL 工具,没有流式处理能力。
- 优先用命令行:
mysql -u root -p database_name ,服务端直接流式读取,不走 GUI 内存模型 - CSV 导入别用「运行 SQL 文件」,改用「导入向导」→ 它底层走
LOAD DATA INFILE,内存开销低一个数量级 - SQL 文件太大?提前拆分:
split -l 5000 full.sql part_(Linux/macOS)或 PowerShell 分批导出,再用 Navicat 批处理作业顺序执行
真正容易被忽略的是:Navicat 的「自动运行任务」在无人交互时反而更危险——系统休眠、GUI 进程挂起会导致连接上下文卡死、内存无法回收。稳定做法是彻底剥离它,把导入逻辑写成独立脚本,用系统定时器调度。











