能跨库,但必须显式写全库名表名;权限须授予definer用户、所有表需为innodb引擎、禁止操作被触发表;事务中全部操作同回滚。

能跨库,但必须显式写全库名表名,且权限、事务、定义者身份三者缺一不可。
跨库操作语法必须带库名前缀
MySQL 触发器本身不关心“当前库”是哪个,它只认你写的表名是否完整。漏写库名,就会默认往当前 USE 的库下找表,轻则插错地方,重则报 ERROR 1146 (42S02): Table 'xxx' doesn't exist。
- 正确写法:
INSERT INTO audit_db.audit_log (event, table_name) VALUES ('INSERT', 'orders'); - 错误写法:
INSERT INTO audit_log (...) VALUES (...);—— 这会去触发器所在库下找audit_log,不是你想写的那个 - 视图、函数、存储过程同理:跨库调用必须写
other_db.vw_summary或other_db.fn_get_status()
ERROR 1442 不是跨库问题,是动了本表
这个错误常被误认为“不能跨库”,其实它只拦截一件事:在触发器里对「正在被触发的那张表」做任何 DML(含 SELECT COUNT(*) 这类只读查询,在某些 MySQL 版本也会触发)。
- 典型错误:
AFTER INSERT ON orders触发器里写UPDATE orders SET updated_at = NOW() WHERE id = NEW.id; - 安全替代:把日志写到
audit_db.audit_log,状态更新逻辑移到应用层或定时EVENT - 想查本表判断状态?优先用
NEW或OLD字段值做分支,别碰表
权限配置必须覆盖定义者 + 操作对象
触发器以 DEFINER 身份运行,不是调用者。哪怕业务账号有所有权限,只要 DEFINER 用户没被授予目标库表的对应权限,就会静默失败或报错。
- 建触发器前先确认:
SHOW GRANTS FOR 'definer_user'@'host'; - 必须显式授权:
GRANT INSERT ON audit_db.audit_log TO 'definer_user'@'%'; - 如果触发器里调了函数:
GRANT EXECUTE ON FUNCTION app_db.gen_id TO 'definer_user'@'%'; -
TRIGGER权限只能按库授予:GRANT TRIGGER ON app_db.* TO 'definer_user'@'%';,不能写成ON app_db.orders
事务一致性依赖引擎,MyISAM 是隐形炸弹
跨库不等于跨事务——只要所有涉及的表都是 InnoDB,整个操作仍包在原事务中,失败会一起回滚。但只要有一张 MyISAM 表参与,原子性就崩了。
- InnoDB 部分可撤回,MyISAM 部分会提前落盘,无法撤销
- 排查时注意:
SHOW CREATE TABLE audit_db.audit_log;看引擎类型 - 生产环境建议统一用 InnoDB,避免混用;若必须用 MyISAM,清理逻辑不要放进触发器
真正容易翻车的地方不在语法,而在权限配置是否覆盖了定义者账户、目标表是否全是 InnoDB、以及业务代码是否完全不知道某张配置表正被某个跨库触发器悄悄修改。











