23.4.6 事件计划程序和 MySQL 特权

要启用或禁用计划事件的执行,必须设置全局event_scheduler系统变量的值。这需要足以设置全局系统变量的特权。参见第 5.1.8.1 节“系统变量特权”

EVENT特权控制事件的创建,修改和删除。可以使用GRANT授予此特权。例如,此GRANT语句为用户jon@ghidora授予名为myschema的模式的EVENT特权:

GRANT EVENT ON myschema.* TO jon@ghidora;

(我们假定此用户帐户已经存在,否则我们希望它保持不变.)

要为该用户授予所有模式的EVENT特权,请使用以下语句:

GRANT EVENT ON *.* TO jon@ghidora;

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

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具有myschemaEVENT特权。还假设该用户具有myschemaSELECT特权,但没有该模式的其他特权。 jon@ghidora可以创建一个新事件,例如:

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

用户 await 一分钟左右,然后执行SELECT * FROM mytable;查询,期望在 table 中看到几个新行。而是,该 table 为空。由于用户没有该 table 的INSERT特权,因此该事件无效。

如果检查 MySQL 错误日志(hostname.err),则可以看到该事件正在执行,但是尝试执行的操作失败:

2013-09-24T12:41:31.261992Z 25 [ERROR] Event Scheduler:
[jon@ghidora][cookbook.e_store_ts] INSERT command denied to user
'jon'@'ghidora' for table 'mytable'
2013-09-24T12:41:31.262022Z 25 [Note] Event Scheduler:
[jon@ghidora].[myschema.e_store_ts] event execution failed.
2013-09-24T12:41:41.271796Z 26 [ERROR] Event Scheduler:
[jon@ghidora][cookbook.e_store_ts] INSERT command denied to user
'jon'@'ghidora' for table 'mytable'
2013-09-24T12:41:41.272761Z 26 [Note] Event Scheduler:
[jon@ghidora].[myschema.e_store_ts] event execution failed.

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

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

检查INFORMATION_SCHEMA.EVENTStabletable 明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语句。在此示例中,已从jon@ghidora用户帐户中删除了模式myschemaEVENT特权:

REVOKE EVENT ON myschema.* FROM jon@ghidora;

Important

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

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

假设已向用户jon@ghidora授予myschema架构上的EVENTINSERT特权。然后,该用户创建以下事件:

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

创建此事件后,root撤消jon@ghidoraEVENT特权。但是,e_insertcontinue 执行,每隔 7 秒在mytable中插入一个新行。如果root发出了以下两个语句中的任何一个,也是如此:

  • DROP USER jon@ghidora;

  • RENAME USER jon@ghidora TO someotherguy@ghidora;

您可以通过在发出DROP USERRENAME USER语句之前和之后检查mysql.eventtable(在本节后面讨论)或INFORMATION_SCHEMA.EVENTStable(请参阅第 24.8 节““ INFORMATION_SCHEMA 事件”table”)来验证是否正确。

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

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

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

用户的EVENT特权存储在mysql.usermysql.dbtable 的Event_priv列中。在这两种情况下,此列均包含值“ Y”或“ N”之一。默认值为“ N”。仅当给定用户具有全局EVENT特权(即,该特权使用GRANT EVENT ON *.*授予)时,该用户的mysql.user.Event_priv才设置为“ Y”。对于架构级别的EVENT特权,GRANTmysql.db中创建一行,并将该行的Db列设置为架构名称,将User列设置为用户名称,并将Event_priv列设置为'Y'。绝对不需要直接操作这些 table,因为GRANT EVENTREVOKE EVENT语句对它们执行必需的操作。

五个状态变量提供了与事件相关的操作的计数(但不是*由事件执行的语句;请参见第 23.8 节“对存储程序的限制”)。这些是:

  • Com_create_event:自上次服务器重新启动以来执行的CREATE EVENT条语句的数量。

  • Com_alter_event:自上次服务器重新启动以来执行的ALTER EVENT条语句的数量。

  • Com_drop_event:自上次服务器重新启动以来执行的DROP EVENT条语句的数量。

  • Com_show_create_event:自上次服务器重新启动以来执行的显示创建事件条语句的数量。

  • Com_show_events:自上次服务器重新启动以来执行的SHOW EVENTS条语句的数量。

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