必须显式授予TRIGGER权限,仅靠ALL PRIVILEGES或CREATE权限不够;TRIGGER不支持表级授权,只能用ON db.或.*;触发器内涉及的每张表还需对应DML权限,调用函数需额外EXECUTE权限,修改触发器还需DROP权限。

必须显式授予 TRIGGER 权限,仅靠 ALL PRIVILEGES ON database.* 或 CREATE 权限完全不够——这是最常被忽略的硬性前提。
GRANT TRIGGER 语法写错就白授权
MySQL 不支持表级 TRIGGER 授权,GRANT TRIGGER ON mydb.orders TO 'user'@'%' 是非法语法,会直接报 ERROR 1064。权限作用域只能是数据库级或全局级:
-
GRANT TRIGGER ON mydb.* TO 'user'@'%'—— 最常用,限制在指定库内 -
GRANT TRIGGER ON *.* TO 'user'@'%'—— 全局权限,生产环境禁用 -
GRANT TRIGGER ON `mydb`.* TO 'user'@'localhost'—— 注意反引号和 host 精确匹配
别写 GRANT TRIGGER ON *.* TO 'user'@'%' 后又以为“只对某张表生效”,MySQL 会按字面意思放行所有库。
触发器里读写的每张表都得单独给 DML 权限
触发器不是独立沙盒。它内部执行的 SQL,对涉及的每张表都要求调用者具备对应权限。比如一个 BEFORE INSERT ON orders 触发器里写了 INSERT INTO logs 和 SELECT id FROM customers,那用户除了 TRIGGER,还得有:
-
INSERT权限 onlogs表 -
SELECT权限 oncustomers表
常见错误现象:ERROR 1142 (42000): INSERT command denied to user 'user'@'%' for table 'logs',但你明明已授 TRIGGER —— 这说明漏了 logs 表的 INSERT 权限。验证方式:运行 SHOW CREATE TRIGGER trigger_name,逐行检查引用了哪些表、做了什么操作。
修改触发器本质是 DROP + CREATE,需要双重权限
MySQL 没有 ALTER TRIGGER,所谓“修改”就是先删再建。这意味着你不仅需要 TRIGGER 权限(用于新建),还需要 DROP 权限(用于删除):
-
GRANT DROP ON mydb.* TO 'user'@'%'—— 库级DROP,比表级更常用 - 若只授
TRIGGER未授DROP,执行DROP TRIGGER时会报ERROR 1142 (42000): DROP command denied - 注意:
DROP权限不继承自ALL PRIVILEGES,必须显式授予
权限变更后,客户端需重连或执行 FLUSH PRIVILEGES(尤其在旧版本或容器环境中)才生效。
EXECUTE 权限容易被连带忽略
如果触发器里调用了自定义函数(如 gen_order_no()),你还得额外授予 EXECUTE 权限:
GRANT EXECUTE ON FUNCTION mydb.gen_order_no TO 'user'@'%'- 函数本身不自动带执行权,哪怕你是创建者,没显式
GRANT EXECUTE就调不了 - 跨库调用函数时(如
sys.get_timestamp()),还要确保用户对sys库有对应函数的EXECUTE权限
权限链断裂往往发生在函数调用这层,而不是触发器创建本身——查 SHOW GRANTS 时容易漏掉这一项。


















