load data 不触发 mysql 触发器是默认行为,因其直接在存储引擎层写入数据页,跳过 sql 解析与执行器的 dml 路径,不生成单行 insert,故无法激活 before/after 触发器钩子。

LOAD DATA 不触发 MySQL 触发器,这是默认行为,不是 bug,也不需要“修复”。
为什么 LOAD DATA 完全绕过触发器
MySQL 的 LOAD DATA INFILE 是一个批量数据导入机制,它在存储引擎层直接写入数据页,跳过了 SQL 解析和执行器的常规 DML 路径。触发器依赖于逐行的 INSERT 执行流程(包括 BEFORE/AFTER 钩子、NEW 行构造、权限校验等),而 LOAD DATA 不生成单行 INSERT 语句,自然不会激活任何触发器。
- 即使表上定义了
BEFORE INSERT或AFTER INSERT触发器,LOAD DATA导入时也完全静默,不报错、不警告、不执行 - 该行为由 MySQL 源码硬编码控制,无法通过配置项开启或关闭(例如没有类似
sql_mode的开关) -
INSERT ... SELECT会触发触发器,但LOAD DATA不会——二者底层路径完全不同
常见误判场景与验证方式
很多团队在迁移或压测时发现审计日志缺失、字段未自动填充、跨表同步失败,第一反应是“触发器没生效”,实际是误用了 LOAD DATA。
- 检查是否真在用
LOAD DATA:执行SHOW PROCESSLIST,看状态是否为Reading from net或Writing to net,而非Query - 验证触发器是否正常:手动执行一条
INSERT INTO ... VALUES (...),观察日志表或字段变更是否发生 - 注意客户端工具行为:某些 GUI 工具(如 Navicat 的“导入向导”)默认走
LOAD DATA,而非拼接 INSERT 语句
替代方案与取舍要点
如果业务逻辑强依赖触发器行为(如自动补全 created_at、写审计日志、校验字段),就不能用 LOAD DATA,必须换路径。
- 改用批量
INSERT:将文件拆成 1000 行/批,拼成INSERT INTO t VALUES (),(),()...,可触发所有触发器,但速度下降 3–5 倍 - 应用层预处理:在导入前用脚本填充
NEW类字段(如时间戳、UUID),再用LOAD DATA导入已完备的数据 - 临时禁用触发器 + 后置补偿:
SET @TRIGGER_CHECKS = 0不生效(MySQL 不支持),只能 DROP 再 CREATE,但高并发下风险极高,不推荐 - 接受不一致并补漏:对关键字段做事后校验(如
SELECT COUNT(*) FROM t WHERE created_at IS NULL),再用 UPDATE 修正
最常被忽略的一点:触发器逻辑一旦被 LOAD DATA 绕过,就等于整个一致性保障链条断了一环——它不像索引或外键那样有报错兜底,而是静默失效。上线前必须明确每种数据写入路径是否覆盖触发器预期。











