MySQL 8.0 参考手册  / 第25章存储对象  / 25.4 使用事件调度器  /  20.4.6 事件调度器和 MySQL 权限

20.4.6 事件调度器和 MySQL 权限

要启用或禁用计划事件的执行,需要设置全局 event_scheduler系统变量的值。这需要足够的权限来设置全局系统变量。请参阅第 5.1.8.1 节,“系统变量权限”

EVENT权限管理事件的创建、修改和删除。可以使用 授予此特权GRANT。例如,此GRANT语句授予对用户 EVENT命名的模式的特权: myschemajon@ghidora

GRANT EVENT ON myschema.* TO jon@ghidora;

(我们假设这个用户帐户已经存在,并且我们希望它保持不变。)

要授予同一用户EVENT 对所有模式的权限,请使用以下语句:

GRANT EVENT ON *.* TO jon@ghidora;

EVENT权限具有全局或架构级范围。因此,尝试在单个表上授予它会导致错误,如下所示:

mysql> GRANT EVENT ON myschema.mytable TO jon@ghidora;
ERROR 1144 (42000): Illegal GRANT/REVOKE command; please
consult the manual to see which privileges can be used

重要的是要了解事件是使用其定义者的特权执行的,并且它不能执行其定义者没有必要特权的任何操作。例如,假设jon@ghidora具有 的 EVENT权限 myschema。还假设该用户拥有 的 SELECT权限 myschema,但没有该架构的其他权限。可以jon@ghidora创建一个新事件,例如:

CREATE EVENT e_store_ts
    ON SCHEDULE
      EVERY 10 SECOND
    DO
      INSERT INTO myschema.mytable VALUES (UNIX_TIMESTAMP());

用户等待一分钟左右,然后执行 SELECT * FROM mytable;查询,希望在表中看到几个新行。相反,表是空的。由于用户没有INSERT 相关表的权限,因此该事件无效。

如果您检查 MySQL 错误日志 ( hostname.err),您可以看到该事件正在执行,但它尝试执行的操作失败,如 所示 RetCode=0

060209 22:39:44 [Note]     EVEX EXECUTING event newdb.e [EXPR:10]
060209 22:39:44 [Note]     EVEX EXECUTED event newdb.e  [EXPR:10]. RetCode=0
060209 22:39:54 [Note]     EVEX EXECUTING event newdb.e [EXPR:10]
060209 22:39:54 [Note]     EVEX EXECUTED event newdb.e  [EXPR:10]. RetCode=0
060209 22:40:04 [Note]     EVEX EXECUTING event newdb.e [EXPR:10]
060209 22:40:04 [Note]     EVEX EXECUTED event newdb.e  [EXPR:10]. RetCode=0

由于该用户很可能无权访问错误日志,因此可以通过直接执行来验证事件的操作语句是否有效:

mysql> INSERT INTO myschema.mytable VALUES (UNIX_TIMESTAMP());
ERROR 1142 (42000): INSERT command denied to user
'jon'@'ghidora' for table 'mytable'

检查 INFORMATION_SCHEMA.EVENTS表显示e_store_ts存在并已启用,但其 LAST_EXECUTED列是 NULL

mysql> SELECT * FROM INFORMATION_SCHEMA.EVENTS
     >     WHERE EVENT_NAME='e_store_ts'
     >     AND EVENT_SCHEMA='myschema'\G
*************************** 1. row ***************************
   EVENT_CATALOG: NULL
    EVENT_SCHEMA: myschema
      EVENT_NAME: e_store_ts
         DEFINER: jon@ghidora
      EVENT_BODY: SQL
EVENT_DEFINITION: INSERT INTO myschema.mytable VALUES (UNIX_TIMESTAMP())
      EVENT_TYPE: RECURRING
      EXECUTE_AT: NULL
  INTERVAL_VALUE: 5
  INTERVAL_FIELD: SECOND
        SQL_MODE: NULL
          STARTS: 0000-00-00 00:00:00
            ENDS: 0000-00-00 00:00:00
          STATUS: ENABLED
   ON_COMPLETION: NOT PRESERVE
         CREATED: 2006-02-09 22:36:06
    LAST_ALTERED: 2006-02-09 22:36:06
   LAST_EXECUTED: NULL
   EVENT_COMMENT:
1 row in set (0.00 sec)

要取消EVENT特权,请使用该REVOKE语句。在此示例中,EVENT架构的权限myschema已从 jon@ghidora用户帐户中删除:

REVOKE EVENT ON myschema.* FROM jon@ghidora;
重要的

撤销EVENT用户的权限不会删除或禁用该用户可能已创建的任何事件。

重命名或删除创建事件的用户不会迁移或删除事件。

假设用户jon@ghidora已被授予对模式的EVENTINSERT权限 myschema。然后该用户创建以下事件:

CREATE EVENT e_insert
    ON SCHEDULE
      EVERY 7 SECOND
    DO
      INSERT INTO myschema.mytable;

创建此事件后,root撤销 的EVENT特权 jon@ghidora。但是, 继续执行,每七秒e_insert插入一个新行。mytable如果root发布了以下任一声明,情况也是如此:

  • DROP USER jon@ghidora;

  • RENAME USER jon@ghidora TO someotherguy@ghidora;

您可以通过在发出or 语句 之前和之后检查mysql.event表(在本节后面讨论)或 INFORMATION_SCHEMA.EVENTS表(参见 第 21.3.8 节,“INFORMATION_SCHEMA EVENTS 表” ) 来验证这是真的 。DROP USERRENAME USER

事件定义存储在mysql.event 表中。要删除由另一个用户帐户创建的事件,MySQL root用户(或具有必要权限的另一个用户)可以从该表中删除行。例如,要删除e_insert前面显示的事件, root可以使用以下语句:

DELETE FROM mysql.event
    WHERE db = 'myschema'
      AND name = 'e_insert';

mysql.event 从表中 删除行时,匹配事件名称和数据库模式名称非常重要。这是因为同名的不同事件可以存在于不同的模式中。

用户的EVENT权限存储在和表的Event_priv列中 。在这两种情况下,此列都包含值“ ”或“ ”之一。' ' 是默认值。 仅当给定用户具有全局权限(即,如果该权限是使用 授予的)时,才会为给定用户设置为 ' ' 。对于模式级 权限, 在中创建一行 并将该行的 列设置为模式名称,将 列设置为用户名,将 列设置为 'mysql.usermysql.dbYNNmysql.user.Event_privYEVENTGRANT EVENT ON *.*EVENTGRANTmysql.dbDbUserEvent_privY'. 永远不需要直接操作这些表,因为GRANT EVENTandREVOKE EVENT语句对它们执行所需的操作。

五个状态变量提供事件相关操作的计数(但包括事件执行的语句;请参阅第 20.8 节,“存储程序的限制”)。这些是:

  • Com_create_eventCREATE EVENT自上次服务器重启以来执行的语句数。

  • Com_alter_eventALTER EVENT自上次服务器重启以来执行的语句数。

  • Com_drop_eventDROP EVENT自上次服务器重启以来执行的语句数。

  • Com_show_create_eventSHOW CREATE EVENT自上次服务器重启以来执行的语句数。

  • Com_show_eventsSHOW EVENTS自上次服务器重启以来执行的语句数。

您可以通过运行语句一次查看所有这些的当前值SHOW STATUS LIKE '%event%';