MySQL5.1.6起增長了事件調度器(Event Scheduler),可用來作定時執行某些特定任務,用於取代原先只能由操做系統的計劃任務來執行的工做。MySQL的事件調度器能夠精確到每秒執行一個任務,而操做系統的計劃任務只能精確到分鐘級別。對於對數據實時性要求比較高的應用很是合適。mysql
事件調度器也稱爲臨時觸發器(Temporal Triggers),由於事件調度器是基於特定時間週期觸發來執行某些任務,而觸發器(Triggers)是基於某個表所產生的事件觸發的。web
MySQL定時任務的實現方式有兩種:sql
event
定時任務 event_scheduler
後才能處理。crontab
如何開啓事件計劃呢?shell
$ SHOW VARIABLES LIKE 'event_scheduler'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | event_scheduler | OFF | +-----------------+-------+ 1 row in set
若是執行命令後返回值爲OFF
則表示目前事件計劃是處於關閉的狀態。json
開啓的方式也分爲兩種,臨時方式使用命令行或腳本操做,永久修改則須要修改MySQL主配置文件my.ini
在其中添加event_schduler=1
的配置後重啓MySQL。vim
臨時性修改只要不重啓MySQL在當前運行狀態下會直接生效,一旦重啓後則失效。ruby
$ SET GLOBAL event_scheduler = ON; $ SET @@global.event_scheduler = ON; $ SET GLOBAL event_scheduler = 1; $ SET @@global.event_scheduler = 1;
要保證可以執行事件,就必須保證事件計劃是開啓狀態,事件計劃默認爲關閉狀態。bash
# 查看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
的配置。服務器
事件任務this
# 查看事件任務 $ 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
設置定時任務執行SQL語句
例如:從當日開始天天凌晨4點刪除fight表超過一個月的數據
計劃任務
DROP EVENT IF EXISTS event_fight_delete; CREATE EVENT event_fight_delete ON SCHEDULE EVERY 1 DAY STARTS DATE_ADD(DATE(CURDATE() + 1), INTERVAL 4 HOUR) DO BEGIN DELETE FROM center_fight WHERE 1=1 AND createdate < DATE_ADD(CURDATE(), INTERVAL -1 MONTH) END
設置定時任務調用存儲過程
# 若計劃任務存在則刪除 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
在兩種計劃任務中,時間戳能夠是任意的TIMESTAMP
和DATETIME
數據類型,時間戳須要大於當前時間。
在重複的計劃任務中,時間(單位)的數量能夠是任意非空(NOT NULL)的整數形式,時間單位是關鍵詞:YEAR
、MONTH
、DAY
、HOUR
、MINUTE
、SECOND
...
[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
出現錯誤
[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
解決方案
$ SELECT VERSION(); $ @@sql_mode; $ SET sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY' , ''));
出現提示
ERROR
# 在SQL中查詢計劃事件的狀態 $ SHOW VARIABLES LIKE 'event_scheduler' # 在mysql程序的目錄下找到my.ini文件添加 $ vim my.ini event_scheduler = 1 # 保存後重啓mysql服務 # 用腳原本實現 # 開啓event_scheduler sql指令: SET GLOBAL event_scheduler = ON; SET @@global.event_scheduler = ON; SET GLOBAL event_scheduler = 1; SET @@global.event_scheduler = 1; $ 關閉event_scheduler指令: SET GLOBAL event_scheduler = OFF; SET @@global.event_scheduler = OFF; SET GLOBAL event_scheduler = 0; SET @@global.event_scheduler = 0;
2人點贊
做者:JunChow520
連接:https://www.jianshu.com/p/917... 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。