LOAD DATA 绕过触发器是设计使然,不是配置问题:它跳过SQL解析与执行路径,直接写入数据页,不触发任何触发器,且无法在触发器内调用,静默失效无提示。
MySQL 的 LOAD DATA INFILE 和 LOAD DATA LOCAL INFILE 从不触发任何触发器,这不是 bug,也不是权限或配置没开对,而是存储引擎层的硬编码行为。它跳过 SQL 解析器和执行器,直接在 InnoDB 数据页写入,根本不走 INSERT 语句的执行路径,自然没有 NEW 行、没有 BEFORE/AFTER 钩子、也没有触发器调度机会。
哪怕你确认了以下所有条件,依然无效:
SELECT @@global.local_infile 返回 ON
SHOW GRANTS 显示用户有 FILE 权限/var/lib/mysql-files/ 或启用了 local_infile 客户端参数ENABLED,且语法完全正确反过来,想在触发器内部主动调用 LOAD DATA 也行不通——MySQL 自 5.0 起就禁止在触发器、存储过程、函数、事件中使用该语句,解析阶段就拦截,报错固定为:ERROR 1314 (42000): LOAD DATA is not allowed in stored procedures, functions, triggers, or events。
这个限制与权限无关,DEFINER 用户有没有 FILE 权限、secure_file_priv 设在哪、甚至用 PREPARE/EXECUTE 动态拼都不起作用。它纯粹是语法层的“黑名单”,服务端上下文不支持。
很多团队上线后发现 created_at 没自动填、操作日志表没记录、跨表关联数据不同步,第一反应是“触发器坏了”,实际是导入脚本用了 LOAD DATA 却没意识到它静默绕过了整个触发逻辑链。
验证是否踩坑,只需两步:
information_schema.TRIGGERS 确认触发器存在且 STATUS = 'ENABLED'
INSERT INTO t VALUES (...),观察预期行为(如日志写入、字段补全)是否发生;若正常,但 LOAD DATA 导入时没反应,基本可锁定是路径差异导致如果业务强依赖触发器行为(比如必须写审计日志、校验字段、自动补全时间戳),就不能用 LOAD DATA,必须换路径:
INSERT INTO ... VALUES (),(),():拆文件为 1000 行/批,拼成单条多值 INSERT,可完整触发所有触发器,但性能下降 3–5 倍created_at、uuid 等字段,再用 LOAD DATA 导入已完备的数据LOAD DATA LOCAL INFILE,但要注意 LOAD DATA 本身不参与事务,主业务回滚时它不会撤回最容易被忽略的一点:触发器被绕过时,没有任何错误、警告或日志提示,它是静默失效的。这意味着一致性保障链条断开得毫无征兆——上线前必须逐条核对所有数据写入路径是否覆盖触发器预期。