MySQL 事件(Event)與事件排程器(Event Scheduler)介紹
前言
事件排程器是在 MySQL 5.1 中新增的另一個特色功能,可以作為定時任務排程器,取代部分原先只能用作業系統任務排程器才能完成的定時功能。而且 MySQL 的事件排程器可以實現每秒鐘執行一個任務,這在一些對實時性要求較高的環境下就非常實用了。
事件排程器是定時觸發執行的,在這個角度上也可以稱作是”臨時的觸發器”。觸發器只是針對某個表產生的事件執行一些語句,而事件排程器則是在某一個(間隔)時間執行一些語句。事件是由一個特定的執行緒來管理的,也就是所謂的”事件排程器”。啟用事件排程器後,擁有 SUPER 許可權的賬戶執行 SHOW PROCESSLIST 就可以看到這個執行緒了。通過設定全域性變數event_scheduler 的值即可動態的控制事件排程器是否啟用。
建立事件
語法
CREATE
[DEFINER = { user | CURRENT_USER }]
EVENT
[IF NOT EXISTS]
event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'string']
DO event_body;
schedule:
AT timestamp [+ INTERVAL interval] ...
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...]
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
語法說明:
- DEFINER:指定可執行該定時器的MySQL賬號,user的格式是’user_name’@’host_name’,CURRENT_USER或CURRENT_USER(),注意,單引號是需要在語句中輸入的。如果不指定,預設是DEFINER = CURRENT_USER。
- event_name:事件名稱,最大64個字元,不區分大小寫,MyEvent和myevent是一樣的,命名規則和其他MySQL物件是一樣的。
- ON SCHEDULE schedule:下文詳細說明。
- [ON COMPLETION [NOT] PRESERVE]:可選,preserve是保持的意思,這裡是說這個定時器第一次執行完成以後是否還需要保持,如果是NOT PRESERVE,該定時器只執行一次,完成後自動刪除事件;沒有NOT,該定時器會多次執行,可以理解為這個定時器是永續性的。預設是NOT PRESERVE。
- [ENABLE | DISABLE | DISABLE ON SLAVE]:可選,是否啟用該事件,ENABLE-啟用,DISABLE-禁用,可使用alter event語句修改該狀態。DISABLE ON SLAVE是指在主備複製的資料庫伺服器中,在備機上也建立該定時器,但是不執行。
- COMMENT: 註釋,必須用單引號括住。
- DO event_body:事件要執行的SQL語句,可以是一個SQL,也可以是使用BEGIN和END的複合語句,和儲存過程相同。
事件的執行時間
ON SCHEDULE指定事件何時執行,執行的頻率和執行的時間段,有AT和EVERY兩種形式。
AT timestamp
AT timestamp用於只執行一次的事件。執行的時間由timestamp指定,timestamp必須包含完整的日期和時間,即年月日時分秒都要有。可以使用DATETIME或TIMESTAMP型別,或者可以轉換成時間的值,例如“2018-01-21 00:00:00”。如果指定是時間是過去的時間,該事件不會執行,並生成警告。
mysql> SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2018-01-21 11:38:21 |
+---------------------+
1 row in set (0.050 sec)
mysql> CREATE EVENT e_totals
-> ON SCHEDULE AT '2018-01-21 11:38:20'
-> DO INSERT INTO test.totals VALUES (NOW());
Query OK, 0 rows affected, 1 warning (0.02 sec)
mysql> show warnings\G
*************************** 1. row ***************************
Level: Note
Code: 1588
Message: Event execution time is in the past and ON COMPLETION
NOT PRESERVE is set. The event was dropped immediately
after creation.
1 row in set (0.01 sec)
這個只執行一次的事件,因為時間定義是過去的時間,所以不會執行,建立以後又被立即刪除。可以使用CURRENT_TIMESTAMP指定執行時間,這樣的話,事件建立成功會立即執行。
如果事件執行的時間是未來的某個時間點,可以使用+ INTERVAL interval指定具體時間。interval有數字(quantity)和時間單位(Unit of time)兩部分組成,例如:2分10秒後執行,應寫為 + INTERVAL ‘2:10’ MINUTE_SECOND。可用的時間單位有很多,列表如下:
unit | 說明 |
---|---|
YEAR | 年 |
QUARTER | 季度 |
MONTH | 月 |
DAY | 天 |
HOUR | 時 |
MINUTE | 分 |
WEEK | 周 |
SECOND | 秒 |
YEAR_MONTH | 年:月 |
DAY_HOUR | 日:時 |
DAY_MINUTE | 日:分 |
DAY_SECOND | 日:秒 |
HOUR_MINUTE | 時:分 |
HOUR_SECOND | 時:秒 |
MINUTE_SECOND | 分:秒 |
示例
這是一個最簡單的示例,1小時後執行該事件:
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE myschema.mytable SET mycol = mycol + 1;
Every interval
如果需要讓事件定時執行,使用Every這種方式。注意EVERY後邊的interval沒有+ INTERVAL,時間格式和單位和上面的相同。
示例:
EVERY 6 WEEK 每六週
EVERY 20 second 每20秒
EVERY後面可以跟可選的STARTS和ENDS,指定事件開始和結束時間,在這個時間段內,時間定時執行。STARTS和ENDS可同時指定,或者只指定STARTS,或兩者都不指定。
示例:
EVERY 3 MONTH STARTS CURRENT_TIMESTAMP + INTERVAL 1 WEEK 一週以後開始,每隔三個月
EVERY 2 WEEK STARTS CURRENT_TIMESTAMP + INTERVAL ‘6:15’ HOUR_MINUTE 六個小時15分鐘以後,每隔兩週
EVERY 12 HOUR STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS CURRENT_TIMESTAMP + INTERVAL 4 WEEK 30分鐘以後開始,4周後結束,每隔12個小時
示例
這個示例是每小時執行一次指定操作:
CREATE EVENT e_hourly
ON SCHEDULE
EVERY 1 HOUR
COMMENT 'Clears out sessions table each hour.'
DO
DELETE FROM site_activity.sessions;
以下是個稍微複雜點的例子,用到了複合語句:
delimiter $$
CREATE EVENT e_daily
ON SCHEDULE
EVERY 1 DAY
COMMENT 'Saves total number of sessions then clears the table each day'
DO
BEGIN
INSERT INTO site_activity.totals (time, total)
SELECT CURRENT_TIMESTAMP, COUNT(*)
FROM site_activity.sessions;
DELETE FROM site_activity.sessions;
END $$
delimiter ;
儲存過程中用到的變數、錯誤處理和流程控制(while,if……)語句在eventbody中都可以使用,有一點區別是,事件不能接收引數。如果需要,可以在事件中呼叫儲存過程,通過儲存過程傳引數。
修改事件
語法
ALTER
[DEFINER = { user | CURRENT_USER }]
EVENT event_name
[ON SCHEDULE schedule]
[ON COMPLETION [NOT] PRESERVE]
[RENAME TO new_event_name]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'string']
[DO event_body]
這裡的關鍵字含義和建立Event語句是一樣的,很好理解,下面給出一些例項幫助大家理解(來自官方文件)。
原始的Event定義如下:
CREATE EVENT myevent
ON SCHEDULE
EVERY 6 HOUR
COMMENT 'A sample comment.'
DO
UPDATE myschema.mytable SET mycol = mycol + 1;
下面的語句,將myevent從當前開始每6個小時執行,改為4個小時候每隔12個小時執行:
ALTER EVENT myevent
ON SCHEDULE
EVERY 12 HOUR
STARTS CURRENT_TIMESTAMP + INTERVAL 4 HOUR;
在一個Alter Event語句中,可以修改Event的多個屬性,下面的語句將myevent修改成1天后刪除mytable表中的所有資料,只執行一次:
ALTER EVENT myevent
ON SCHEDULE
AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
DO
TRUNCATE TABLE myschema.mytable;
禁用事件:
ALTER EVENT myevent DISABLE;
修改事件名稱:
ALTER EVENT myevent RENAME TO yourevent;
更進一步,可以將事件從一個數據庫移動到另外一個數據庫:
ALTER EVENT olddb.myevent RENAME TO newdb.myevent;
檢視事件
MySQL的information_schema提供了訪問資料庫元資料的方式。 元資料是關於資料的資料,如資料庫名或表名,列的資料型別,或訪問許可權等。其中Events表中可以檢視所有已定義的事件的具體資訊,包括事件所屬庫名稱、事件名稱、事件型別、事件的完整定義、開始時間、INTERVAL定義、上一次執行時間等等。
示例:
mysql> SELECT * FROM EVENTS\G
*************************** 1. row ***************************
EVENT_CATALOG: def
EVENT_SCHEMA: ^^^^^^ --資料庫名稱
EVENT_NAME: ev_xxzh_tranhistory
DEFINER: ^^^^^^^^^^^
TIME_ZONE: SYSTEM
EVENT_BODY: SQL
EVENT_DEFINITION: BEGIN
call sp_xxzh_transhistory();
END
EVENT_TYPE: RECURRING
EXECUTE_AT: NULL
INTERVAL_VALUE: 1
INTERVAL_FIELD: DAY
SQL_MODE: NO_ENGINE_SUBSTITUTION
STARTS: 2017-10-19 05:30:00
ENDS: NULL
STATUS: SLAVESIDE_DISABLED
ON_COMPLETION: PRESERVE
CREATED: 2017-10-19 18:00:26
LAST_ALTERED: 2017-10-19 18:00:26
LAST_EXECUTED: NULL
EVENT_COMMENT:
ORIGINATOR: 110
CHARACTER_SET_CLIENT: utf8
COLLATION_CONNECTION: utf8_general_ci
DATABASE_COLLATION: utf8_general_ci
Events表中的欄位名稱含義都很清晰,這裡不再詳細描述。
刪除事件
刪除事件的語句很簡單:
drop event myevent;
事件排程器
啟動事件排程器
SET GLOBAL event_scheduler = ON;
SET @@global.event_scheduler = ON;
SET GLOBAL event_scheduler = 1;
SET @@global.event_scheduler = 1;
關閉事件排程器
SET GLOBAL event_scheduler = OFF;
SET @@global.event_scheduler = OFF;
SET GLOBAL event_scheduler = 0;
SET @@global.event_scheduler = 0;
檢視事件排程器狀態
show variables like "event_scheduler";
查詢結果:
mysql> show variables like "event_scheduler";
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | ON |
+-----------------+-------+
1 row in set (0.04 sec)
如果當前事件排程器是關閉的,使用上面啟動事件排程器的命令開啟即可。使用命令的方式開啟,資料庫伺服器重新啟動後,事件排程器會恢復到關閉狀態。如果想要預設啟動事件排程器,可以通過修改配置檔案my.cnf實現。具體做法是開啟my.cnf檔案,在[mysqld]下面新增一行:
event_scheduler = ON
即可。