第 39.1 节:创建事件

MySQL 提供了事件功能,避免在大部分调度工作与 SQL 相关、与文件相关较少时使用复杂的 cron 交互。更多信息请参阅手册。可将事件视为按重复间隔计划运行的存储过程。

为节省调试事件相关问题的时间,请记住全局事件处理程序必须开启才能处理事件。

SHOW VARIABLES WHERE variable_name='event_scheduler';

结果示例:

+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | OFF   |
+-----------------+-------+

如果为 OFF,则任何事件都不会触发。因此需开启:

SET GLOBAL event_scheduler = ON;

测试用表结构

CREATE TABLE theMessages (
    id INT AUTO_INCREMENT PRIMARY KEY,
    userID INT NOT NULL,
    message VARCHAR(255) NOT NULL,
    updateDt DATETIME NOT NULL,
    KEY(updateDt)
);

INSERT INTO theMessages (userId, message, updateDt) VALUES
(1, 'message 123', '2015-08-24 11:10:09'),
(7, 'message 124', '2015-08-29 00:00:00'),
(1, 'message 125', '2015-09-03 12:00:00'),
(1, 'message 126', '2015-09-03 14:00:00');

以上插入仅为展示起点。下面创建的两个事件将用于清理数据。

创建两个事件:第 1 个每天运行,第 2 个每 10 分钟运行

重点在于 INTERVAL 和调度设置,而不是它们实际做什么(彼此配合)。

DROP EVENT IF EXISTS `delete7Day01dMessages`;
DELIMITER $$
CREATE EVENT `delete7Day01dMessages`
ON SCHEDULE EVERY 1 DAY STARTS '2015-09-01 00:00:00'
ON COMPLETION PRESERVE
DO
BEGIN
    DELETE FROM theMessages WHERE DATEDIFF(NOW(), updateDt) > 6;
    -- 其他代码
END$$
DELIMITER ;
DROP EVENT IF EXISTS `Every_10_Minutes_Cleanup`;
DELIMITER $$
CREATE EVENT `Every_10_Minutes_Cleanup`
ON SCHEDULE EVERY 10 MINUTE STARTS '2015-09-01 00:00:00'
ON COMPLETION PRESERVE
DO
BEGIN
    DELETE FROM theMessages WHERE TIMESTAMPDIFF(HOUR, updateDt, NOW()) > 168;
    -- 消息超过一周(168 小时)
    -- 其他代码
END$$
DELIMITER ;

显示事件状态(不同方法)

SHOW EVENTS FROM my_db_name;   -- 按数据库名列出所有事件
SHOW EVENTS;
SHOW EVENTS\G;                 -- 在 mysql 提示符下推荐的方式

输出示例:

*************************** 1. row ***************************
                  Db: my_db_name
                Name: delete7DayOldMessages
             Definer: root@localhost
           Time zone: SYSTEM
                Type: RECURRING
          Execute at: NULL
      Interval value: 1
      Interval field: DAY
              Starts: 2015-09-01 00:00:00
                Ends: NULL
              Status: ENABLED
          Originator: 1
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
*************************** 2. row ***************************
                  Db: my_db_name
                Name: Every_10_Minutes_Cleanup
             Definer: root@localhost
           Time zone: SYSTEM
                Type: RECURRING
          Execute at: NULL
      Interval value: 10
      Interval field: MINUTE
              Starts: 2015-09-01 00:00:00
                Ends: NULL
              Status: ENABLED
          Originator: 1
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
2 rows in set (0.06 sec)

其他注意事项

DROP EVENT someEventName;   -- 删除事件及其代码
  • ON COMPLETION PRESERVE - 事件处理完成后保留它。否则会被删除。
  • 事件类似于触发器。它们不是由用户程序调用的,而是按计划执行的。因此,它们成功或失败都是静默的。

手册页面显示了间隔选项的灵活性,如下所示:

interval:
    quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}

事件是处理系统定期和计划任务的强大机制。它们可以包含任意数量的语句、DDL 和 DML 例程,以及合理希望的复杂连接。请参阅 MySQL 手册《存储程序的限制》。