MySQL 定時任務

MySQL5.1.6起增加了事件調度器(Event Scheduler),可用來做定時執行某些特定任務,用於取代原先只能由操作系統的計劃任務來執行的工作。MySQL的事件調度器可以精確到每秒執行一個任務,而操作系統的計劃任務只能精確到分鐘級別。對於對數據實時性要求比較高的應用非常合適。

事件調度器也稱爲臨時觸發器(Temporal Triggers),因爲事件調度器是基於特定時間週期觸發來執行某些任務,而觸發器(Triggers)是基於某個表所產生的事件觸發的。

MySQL定時任務的實現方式有兩種:

  • 常規使用MySQL的event定時任務
  • 使用Linux的定時任務crontab

事件調度器

要保證能夠執行事件,就必須保證事件計劃是開啓狀態,事件計劃默認爲關閉狀態。

# 查看MySQL版本
$ SELECT VERSION();
+------------+
| VERSION()  |
+------------+
| 5.7.18-log |
+------------+
1 row in set

# 事件計劃是否開啓
$ SHOW VARIABLES LIKE 'event%'
$ SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | ON    |
+-----------------+-------+
1 row in set

# 查看事件任務是否開啓
$ SELECT @@event_scheduler;
+-------------------+
| @@event_scheduler |
+-------------------+
| ON                |
+-------------------+
1 row in set

# 開啓事件計劃
$ SET GLOBAL event_scheduler=1
$ SET GLOBAL event_scheduler=ON
duler=1;
Query OK, 0 rows affected

# 關閉事件計劃
$ SET GLOBAL event_scheduler=0

在真實開發環境中會遇到MySQL服務重啓或斷電的情況,此時會出現事件調度器被關閉的情況。所有事件都不再起作用,解決的方式需要在MySQL的配置文件mysql.ini中加入event_scheduler=ON的配置。

事件任務

事件任務

# 查看事件任務
$ SHOW EVENTS;
Empty set

# 查看事件任務錯誤 - 權限不足
$ SELECT * FROM mysql.event
1142 - SELECT command denied to user 'username'@'127.0.0.1' for table 'event'

# 開啓事件任務
$ ALTER EVENT event_name ON COMPLETION PRESERVE ENABLE

# 關閉事件任務
$ ALTER EVENT event_name ON COMPLETION PRESERVE DISABLE

# 刪除事件
$ DROP EVENT [IF EXISTS] event_name

設置定時任務調用存儲過程

# 若計劃任務存在則刪除
DROP EVENT IF EXISTS event_name
# 創建計劃任務
CREATE EVENT event_name
  ON SCHEDULE EVERY 10 second 
  STARTS TIMESTAMP '2018-07-12 00:00:00'
  ON COMPLETION PRESERVE
DO
  BEGIN CALL producer()
END

參數說明

  • ON SCHDULE schduler 定義執行的時間和時間間隔
  • ON COMPLETION [NOT] PRESERVE 定義事件是一次性執行還是永久執行,默認爲一次性執行,即NOT PRESERVE

在事件中ON SCHEDULE計劃任務中有2種設定的方式

  • 用來完成單次計劃任務。
AT 時間戳

eg:5天后
AT CURRENT_TIMESTAMP + INTERVAL 5 DAY

eg:某時間點
AT TIMESTAMP '2018-07-12 12:00:00'
  • 用來完成重複的計劃任務
EVERY 時間(單位)的數量 時間單位 [STARTS 時間戳] [ENDS時間戳]

eg:每隔1秒
EVERY 1 SECOND

eg:每隔10分鐘。
EVERY 10 MINUTE

eg:從2018-08-01 12:00:00開始每隔1天
EVERY 1 DAY STARTS '2018-08-01 12:00:00'
EVERY 10 second STARTS TIMESTAMP '2018-08-01 12:00:00'

eg:5天后開啓每天定時處理
EVERY 1 DAY START CURRENT_TIMESTAMP + INTERVAL 5 DAY

eg:每天定時處理5天后停止
EVERY 1 DAY ENDS CURRENT_TIMESTAMP + INTERVAL 5 DAY

在兩種計劃任務中,時間戳可以是任意的TIMESTAMPDATETIME數據類型,時間戳需要大於當前時間。

在重複的計劃任務中,時間(單位)的數量可以是任意非空(NOT NULL)的整數形式,時間單位是關鍵詞:YEARMONTHDAYHOURMINUTESECOND...

[ON COMPLETION [NOT] PRESERVE]

ON COMPLETION參數表示“當這個事件不會再發生的時候”,即當單次計劃任務執行完畢後或當重複性的計劃任務執行到了ENDS階段。而PRESERVE的作用是使事件在執行完畢後不會被DROP掉,建議使用該參數,以便於查看EVENT具體信息。

CREATE DEFINER=`root`@`localhost` EVENT `event_knapsacks_remember_expire` 
ON SCHEDULE EVERY 1 MINUTE STARTS '2018-07-13 15:09:49' 
ON COMPLETION PRESERVE ENABLE 
COMMENT '每分鐘檢測揹包中換牌卡到期並每日自動減少' 
DO 
BEGIN 
    CALL produce_knapsacks_remember_expire();
END

存儲過程

DELIMITER $$
  DROP PROCEDURE IF EXISTS procedure_name
  CREATE PROCEDURE procedure_name()
  BEGIN
    INSERT INTO procedure_name(name, create_time) VALUES('name_value', now())
  END $$
DELIMITER ;
-- 存儲過程 produce_knapsacks_remember_expire
-- 作用:判斷揹包中道具記牌卡,是否過期,且每日減一。

CREATE DEFINER=`root`@`localhost` PROCEDURE `produce_knapsacks_remember_expire`()
BEGIN
    DECLARE pk INT DEFAULT 0;
    DECLARE sec INT DEFAULT 0;
    DECLARE days INT DEFAULT 0;
    DECLARE expire INT DEFAULT 0;
    DECLARE mc CURSOR FOR (SELECT id,TIMESTAMPDIFF(SECOND,effect_time,NOW()) AS diff,TIMESTAMPDIFF(SECOND,NOW(),expire_time) AS expire FROM knapsacks WHERE name='REMEBER' AND expired=0);
    OPEN mc;
    ml:LOOP
    FETCH mc INTO pk,sec,expire;

    IF(expire <= 0) THEN
        UPDATE `knapsacks` SET `expired`=1 WHERE `id`=pk;
    ELSE
        IF(sec>0 && sec<=86400) THEN
            SET days = 1;
        ELSEIF(sec>86400) THEN
            SET days=CEILING(sec/86400);
        END IF;
        UPDATE `knapsacks` SET `quantity`=`purchase`-days,`consume`=days WHERE `id`=pk;
    END IF;

    COMMIT;
    END LOOP ml;
    CLOSE mc;
END

 


給大佬遞茶:
作者:JunChow520
鏈接:MySQL定時任務
來源:簡書

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章