MySQL 学习笔记 3:Event

MySQL 学习笔记 3:Event

MySQL 学习笔记 3:Event_第1张图片

图源:ubiq.co

在 MySQL 中,用事件(Event)表示和定义一个定时任务。

我们可以利用事件执行一些定时任务,比如定期生成统计数据、清理和转储日志表等。

启用事件

在使用事件之前需要先检查 MySQL 是否开启了事件功能:

mysql> SELECT @@event_scheduler;
+-------------------+
| @@event_scheduler |
+-------------------+
| ON                |
+-------------------+
1 row in set (0.00 sec)

或使用:

mysql> SHOW VARIABLES LIKE 'event%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | ON    |
+-----------------+-------+
1 row in set, 1 warning (0.01 sec)

ON表示开启,OFF表示关闭。

可以通过以下语句启用和关闭事件功能:

SET GLOBAL event_scheduler = ON;
SET GLOBAL event_scheduler = OFF;

这样的方式开启或关闭事件会在 MySQl 重启后失效,如果有需要,可以在 MySQL 的配置文件my.cnf中添加:

event_scheduler=1

创建

用 SQLyog 创建事件会出现以下创建语句模版:

DELIMITER $$

-- SET GLOBAL event_scheduler = ON$$     -- required for event to execute but not create    

CREATE	/*[DEFINER = { user | CURRENT_USER }]*/	EVENT `jpa`.`stat_student_score`

ON SCHEDULE
	 /* uncomment the example below you want to use */

	-- scheduleexample 1: run once

	   --  AT 'YYYY-MM-DD HH:MM.SS'/CURRENT_TIMESTAMP { + INTERVAL 1 [HOUR|MONTH|WEEK|DAY|MINUTE|...] }

	-- scheduleexample 2: run at intervals forever after creation

	   -- EVERY 1 [HOUR|MONTH|WEEK|DAY|MINUTE|...]

	-- scheduleexample 3: specified start time, end time and interval for execution
	   /*EVERY 1  [HOUR|MONTH|WEEK|DAY|MINUTE|...]

	   STARTS CURRENT_TIMESTAMP/'YYYY-MM-DD HH:MM.SS' { + INTERVAL 1[HOUR|MONTH|WEEK|DAY|MINUTE|...] }

	   ENDS CURRENT_TIMESTAMP/'YYYY-MM-DD HH:MM.SS' { + INTERVAL 1 [HOUR|MONTH|WEEK|DAY|MINUTE|...] } */

/*[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE]
[COMMENT 'comment']*/

DO
	BEGIN
	    (sql_statements)
	END$$

DELIMITER ;

创建事件的语句可以分为以下部分:

  • CREATE ... EVENT ...,定义事件名称。包含一个可选的DEFINER语句,可以指定用户的使用权限。
  • ON SCHEDULE ...,定义事件执行的时间点或周期,可以用STARTSENDS指定事件的有效期。
  • ON COMPLETION [NOT] PRESERVE,可选,如果设置成``ON COMPLETION PRESERVE,事件到期后依然会被保留,如果设置成ON COMPLETION NOT PRESERVE`,事件到期后会被删除。
  • [ENABLE | DISABLE],可选,ENABLE为启用,DISABLE为停用。
  • [COMMENT 'comment'],可选,注释。
  • DO ...,事件执行的具体 SQL,如果是多条,可以使用BEGINEND包裹。

下面我们看几个具体示例。

单次定时任务

下面这个事件将在指定时间点运行:

DELIMITER $$

CREATE	EVENT `jpa`.`insert_sys_msg`

ON SCHEDULE
	AT '2023-07-11 15:59:00'
DO
	BEGIN
	    INSERT INTO `jpa`.`sys_msg` (`msg`, `time`) VALUES ('hello', NOW()); 
	END$$

DELIMITER ;

结果:

mysql> select * from sys_msg;
+----+-------+---------------------+
| id | msg   | time                |
+----+-------+---------------------+
|  1 | 222   | 2023-07-11 15:54:14 |
|  2 | hello | 2023-07-11 15:59:00 |
+----+-------+---------------------+

还可以观察到这个事件已经被从服务器自动删除了,所以事件默认是ON COMPLETION NOT PRESERVE

除了直接指定时间字符串以外,还可以用当前时间点+时间段的方式指定在某个时间段后执行:

DELIMITER $$

CREATE	EVENT `jpa`.`create_sys_msg`

ON SCHEDULE
	   AT CURRENT_TIMESTAMP + INTERVAL 2 MINUTE
DO
	BEGIN
	    INSERT INTO `jpa`.`sys_msg` (`msg`, `time`) VALUES ('hello', NOW()); 
	END$$

DELIMITER ;

这里的AT CURRENT_TIMESTAMP + INTERVAL 2 MINUTE意味着事件将在创建好后的2分钟后执行。

就像模版 SQL 中的注释内容那样,时间段的单位可以是[HOUR|MONTH|WEEK|DAY|MINUTE|...]中的任意一种。

循环定时任务

大多数定时任务都会被要求以固定的事件间隔执行,比如:

DELIMITER $$

CREATE	EVENT `jpa`.`create_sys_msg`

ON SCHEDULE
	EVERY 1 MINUTE
	comment '每分钟插入一条系统消息'
DO
	BEGIN
	    INSERT INTO `jpa`.`sys_msg` (`msg`, `time`) VALUES ('hello', NOW()); 
	END$$

DELIMITER ;

这个事件将在被创建后每分钟执行一次。

结果:

mysql> select * from sys_msg;
+----+-------+---------------------+
| id | msg   | time                |
+----+-------+---------------------+
|  4 | hello | 2023-07-11 16:16:57 |
|  5 | hello | 2023-07-11 16:17:57 |
|  6 | hello | 2023-07-11 16:18:57 |
+----+-------+---------------------+

有时候我们希望事件在固定时间点循环执行,比如每小时的0分、5分、15分这样(类似 Linux crontable 的*/5)。这点可以通过使用STARTS语句让事件在固定时间点开启来实现。

比如:

DELIMITER $$

CREATE	EVENT `jpa`.`create_sys_msg`

ON SCHEDULE
	   EVERY 5 MINUTE
	   STARTS '2023-07-11 16:30:00'
COMMENT '每5分钟执行一次'

DO
	BEGIN
	    INSERT INTO `jpa`.`sys_msg` (`msg`, `time`) VALUES ('hello', NOW()); 
	END$$

DELIMITER ;

执行结果:

mysql> select * from sys_msg;
+----+-------+---------------------+
| id | msg   | time                |
+----+-------+---------------------+
| 11 | hello | 2023-07-11 16:30:00 |
| 12 | hello | 2023-07-11 16:35:00 |
+----+-------+---------------------+

STARTSENDS同样可以使用当前时间戳+时间段的方式指定,虽然这么做不太常见:

DELIMITER $$

CREATE	EVENT `jpa`.`create_sys_msg`

ON SCHEDULE
	   EVERY 1 HOUR
       STARTS CURRENT_TIMESTAMP+INTERVAL 1 DAY 
       ENDS CURRENT_TIMESTAMP+INTERVAL 3 DAY 
COMMENT '每小时执行一次'

DO
	BEGIN
	    INSERT INTO `jpa`.`sys_msg` (`msg`, `time`) VALUES ('hello', NOW()); 
	END$$

DELIMITER ;

这个事件将在1天后的此时开始执行,并在3天后的此时结束执行。

修改事件

用 SQLyog 执行修改事件操作,会出现类似下面的内容:

DELIMITER $$

ALTER DEFINER=`root`@`localhost` EVENT `create_sys_msg` 
ON SCHEDULE EVERY 5 MINUTE 
STARTS '2023-07-11 16:30:00' 
ON COMPLETION NOT PRESERVE 
ENABLE 
COMMENT '每5分钟执行一次' 
DO 
	BEGIN
	    INSERT INTO `jpa`.`sys_msg` (`msg`, `time`) VALUES ('hello', NOW()); 
	END$$
	
DELIMITER ;

所以ALTER ... EVENT ...语句可以用于修改事件。

删除事件

可以直接用 SQLyog 删除选中事件,但也可以直接使用 SQL 语句删除:

我这版 SQLyog 将删除事件的选项翻译为"放置事件"。

DROP EVENT [IF EXISTS] event_name;

在事件中使用存储过程

与触发器不同的是,在事件中可以直接调用存储过程,比如:

DELIMITER $$

CREATE	EVENT `jpa`.`stat_student`

ON SCHEDULE
	   EVERY 10 MINUTE
DO
	BEGIN
    	declare var_avg_score int;
		declare var_sum_score int;
	    call showScoreAvg(0, 1, 10000, var_avg_score, var_sum_score);
	    insert into `jpa`.`student_stat` (`avg_score`,`total_score`,`time`) values(var_avg_score, var_sum_score,NOW());
	END$$

DELIMITER ;

这里的存储过程示例showScoreAvg来自这篇文章。

The End,谢谢阅读。

参考资料

  • MySQL定时任务(EVENT|事件)如何配置,必会技能!

你可能感兴趣的:(MYSQL,mysql,event,定时任务)