触发器执行失败报access denied或error 1419,根本原因是mysql严格按definer用户身份校验权限,而非当前登录用户;需确认definer账号存在、具备跨库dml权限、log_bin_trust_function_creators启用且触发器状态为enabled。

触发器执行失败报 Access denied for trigger execution 或 ERROR 1419,根本不是“权限没给够”,而是 MySQL 严格按 DEFINER 用户身份校验权限——它完全不看你当前登录的是谁,只认触发器定义里写死的那个用户是否存在、有没有对应表的 DML 权限、是否被 binlog 机制信任。
查 SHOW CREATE TRIGGER 确认真实 DEFINER 是谁
GUI 工具(如 Navicat)生成的 DEFINER=CURRENT_USER() 实际取的是认证用户(比如 'app'@'10.0.2.%'),不是你连工具时用的账号。迁移、重建或账号删改后,这个用户很可能已不存在。
- 必须运行
SHOW CREATE TRIGGER trigger_name;,紧盯输出中DEFINER=`xxx`@`yyy`这一行 - 如果看到
DEFINER=CURRENT_USER或为空,MySQL 仍会固化创建时刻的CURRENT_USER(),需手动验证该账号是否存在 -
SELECT User, Host FROM mysql.user WHERE User = 'xxx';—— 注意大小写和Host必须完全匹配,'admin'@'localhost'和'admin'@'%'是两个独立账号
验证 DEFINER 用户是否存在且有跨库操作权限
DEFINER 不是名字对就行,它必须是真实账号,且对触发器内所有 SQL 涉及的库、表、甚至调用的存储过程,都有最小必要权限。
- 查权限:
SHOW GRANTS FOR 'xxx'@'yyy';,重点核对是否含INSERT ON log_db.audit_log、UPDATE ON sales.orders这类语句 - 若触发器跨库操作(比如从
sales库 UPDATEreport库的表),DEFINER必须对两个库都单独授过权 - MySQL 8.0+ 还要确认是否授予了
SYSTEM_VARIABLES_ADMIN(尤其当触发器读取系统变量或调用函数时) - 云数据库(如阿里云 RDS)通常禁用
GRANT ALL ON *.*,全局授权不仅无效,还可能被平台拒绝
检查 log_bin_trust_function_creators 是否启用
只要 log_bin=ON(MySQL 5.7+ 默认开启),含 NOW()、UUID()、子查询等非确定性操作的触发器,就必须让 MySQL 信任这个 DEFINER。
- 临时生效:
SET GLOBAL log_bin_trust_function_creators = 1;(需SYSTEM_VARIABLES_ADMIN权限) - 持久化:在
my.cnf的[mysqld]段加log_bin_trust_function_creators=1 - 云数据库上硬加
SUPER权限无效,且可能被自动回收,这是唯一可行路径 - 该设置只影响“是否允许创建/执行非确定性函数”,不替代
DEFINER本身的权限校验
确认触发器状态是否为 ENABLED
MySQL 不会提示触发器被禁用了,它只藏在系统表里。执行失败前,先确认它真的在工作。
- 运行
SELECT TRIGGER_NAME, STATUS FROM information_schema.TRIGGERS WHERE TRIGGER_NAME = 'your_trigger_name'; - STATUS 必须是
ENABLED才算激活;若为DISABLED,MySQL 5.7 不支持ALTER TRIGGER ... ENABLE,只能DROP TRIGGER后重建 -
SHOW TRIGGERS LIKE 'table_name';更快,但只查当前库;跨库必须先USE db_name
最容易被忽略的是:触发器执行失败时,错误常被静默吞掉。执行完 INSERT/UPDATE 后立刻跑 SHOW WARNINGS;,往往能捕获真实报错;另外,TRUNCATE 是 DDL,天然不触发任何 DML 类型触发器,这点和权限无关,但常被误判为权限问题。











