EVENT权限是系统级特权,需显式授予用户+主机组合,不依附于具体库表;必须开启event_scheduler才能执行事件;事件执行依赖DEFINER账户权限,而非创建者权限。

EVENT权限不是普通数据库权限,而是系统级特权
MySQL的EVENT权限控制的是创建、修改、删除事件的能力,它不作用于某张表或某个库,而是绑定在用户+主机组合上,且必须显式授予。它和SELECT、INSERT这类对象权限不同,不能用GRANT ... ON table.*语法给到具体对象;它只存在于mysql.db(库级)或mysql.user(全局)表中,对应字段是event_priv。
常见错误是误以为只要给了ALL PRIVILEGES ON db.*就自动包含EVENT——其实不会。即使用户对数据库有全部DML权限,没单独授EVENT,CREATE EVENT仍会报错:ERROR 1227 (42501): Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation(注意:这个错误提示容易误导,实际缺的是EVENT权限,不是SUPER)。
- 授予库级EVENT权限(推荐):
GRANT EVENT ON myapp.* TO 'worker'@'192.168.1.%'; - 授予全局EVENT权限(仅限DBA):
GRANT EVENT ON *.* TO 'admin'@'localhost'; - 撤销权限:
REVOKE EVENT ON myapp.* FROM 'worker'@'192.168.1.%'; - 确认是否生效:
SELECT event_priv FROM mysql.db WHERE Db='myapp' AND User='worker';(返回Y才表示成功)
event_scheduler=ON不是权限问题,但没开就根本执行不了事件
event_scheduler是个全局系统变量,控制整个实例的调度器开关。它和用户权限无关,但直接决定事件能否运行。即使你把EVENT权限给了10个用户,event_scheduler是OFF,所有事件都处于“挂起”状态,SHOW EVENTS里能看到状态是SLAVESIDE_DISABLED或DISABLED,但不会触发。
启用方式分临时和永久两种:
- 临时开启(重启失效):
SET GLOBAL event_scheduler = ON;(需要SYSTEM_VARIABLES_ADMIN或旧版SUPER权限) - 永久生效(必须配置):在
my.cnf的[mysqld]段下加一行:event_scheduler = ON,然后重启MySQL - 检查状态:
SHOW VARIABLES LIKE 'event_scheduler';(值为ON才算真正启用)
主从环境要特别注意:通常只在主库开event_scheduler,从库保持OFF。否则从库自己也跑定时任务,可能和主库同步冲突,甚至卡住SQL线程。
创建事件时DEFINER和EXECUTE权限分离很关键
一个事件实际执行时,用的是DEFINER账户的权限,而不是调用者(比如你用root创建,DEFINER设为'worker'@'192.168.1.%'),那么事件内所有SQL都以worker身份执行。这意味着:
-
worker必须拥有事件体中每条SQL所需的权限(比如DELETE、INSERT等),光有EVENT权限不够 - 如果事件里调用存储过程,
worker还得有EXECUTE权限(不是CREATE ROUTINE) - 建议显式指定
DEFINER,避免默认用当前用户导致权限混乱:CREATE DEFINER='worker'@'192.168.1.%' EVENT clean_logs ... - 别用
DEFINER='root'@'localhost'配普通应用账号——这等于把root权限借给定时任务,违背最小权限原则
SHOW EVENTS看不到事件?先查三个地方
用户常以为授了EVENT权限就能看到所有事件,其实SHOW EVENTS只显示当前用户有EVENT权限的数据库下的事件。如果你用worker登录,只对myapp库有EVENT权限,那SHOW EVENTS默认只查myapp,不会列出其他库的事件。
- 查当前库的事件:
SHOW EVENTS; - 查指定库的事件:
SHOW EVENTS IN otherdb; - 查所有事件(需
SELECT权限到information_schema):SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA = 'myapp'; - 查事件定义(需
EVENT权限且事件属于该用户可访问库):SHOW CREATE EVENT clean_logs;
最易忽略的一点:事件被DROP后不会留痕,information_schema.EVENTS里也不会出现。如果发现事件“突然没了”,大概率是被DROP EVENT或CREATE OR REPLACE EVENT覆盖掉了,而不是权限或调度器问题。











