Navicat 默认导入不保证原子性,因其逐条执行INSERT且不自动包裹事务;必须手动勾选“使用事务”并验证查询日志中存在BEGIN/COMMIT/ROLLBACK才生效。

Navicat 本身不自动开启事务来包裹导入操作,必须手动启用“事务模式”才能保障一致性。默认情况下,Navicat 的「导入向导」或拖拽 CSV 导入会逐条执行 INSERT,每条语句独立提交——一旦中途失败,已插入的数据不会回滚,导致部分写入、状态不一致。
为什么默认导入不保证原子性
Navicat 的图形化导入本质是客户端模拟批量 INSERT 语句发送给服务端,它不隐式加 BEGIN/COMMIT 包裹整个过程。尤其在以下场景风险极高:
- 目标表有唯一键冲突,某条记录失败后,前面成功的记录仍留在库中
- 导入中途网络中断或客户端崩溃,服务端已收到并提交了前 N 条
- 并发写入同一张表时,没事务隔离可能读到中间态(如部分字段更新未完成)
必须勾选“使用事务”选项并确认生效
在「导入向导」最后一步或「高级选项」中,明确找到并勾选:使用事务(部分版本显示为 Enable transaction 或 Rollback on error)。该选项实际作用是让 Navicat 在导入前发送 BEGIN,全部成功后发 COMMIT,任一失败则发 ROLLBACK。
- 不是所有导入格式都支持该选项(例如某些 Excel 导入路径可能隐藏该开关)
- 若目标表引擎是 MyISAM,事务无效——务必确认表为 InnoDB
- 大文件导入时,事务过长可能触发
innodb_lock_wait_timeout或填满 undo log,建议单次控制在 10 万行以内
导入后必须验证事务是否真被触发
不能只看界面提示“导入成功”。打开 Navicat 的「查询日志」(菜单栏:工具 → 查询日志),搜索关键字:BEGIN、COMMIT 或 ROLLBACK。如果日志里没有这些语句,说明事务根本没启用,导入仍是裸执行。
- 有些低版本 Navicat(如 v12 之前)在「导入向导」中勾选了事务,但底层仍用多条独立
INSERT+ 自动提交 - 若日志里只有大量
INSERT INTO ... VALUES (...)而无事务控制语句,应改用 SQL 脚本方式:手写带BEGIN/COMMIT的批量脚本,在查询编辑器中执行 - 对关键业务表,建议先导出当前行数:
SELECT COUNT(*) FROM table_name,再导入,完成后立刻再查一次并比对——但注意COUNT(*)在高并发下也可能不准,仅作快速筛查
事务开关只是起点,真正难的是判断它是否生效、在哪一层失效(客户端?驱动?服务端?),以及如何在失败后快速定位哪一行触发了回滚。这些细节藏在日志和引擎行为里,而不是勾选框里。


















