MySQL定時(shí)任務(wù)

MySQL5.1.6起增加了事件調(diào)度器(Event Scheduler),可用來(lái)做定時(shí)執(zhí)行某些特定任務(wù),用于取代原先只能由操作系統(tǒng)的計(jì)劃任務(wù)來(lái)執(zhí)行的工作。MySQL的事件調(diào)度器可以精確到每秒執(zhí)行一個(gè)任務(wù),而操作系統(tǒng)的計(jì)劃任務(wù)只能精確到分鐘級(jí)別。對(duì)于對(duì)數(shù)據(jù)實(shí)時(shí)性要求比較高的應(yīng)用非常合適。

事件調(diào)度器也稱(chēng)為臨時(shí)觸發(fā)器(Temporal Triggers),因?yàn)槭录{(diào)度器是基于特定時(shí)間周期觸發(fā)來(lái)執(zhí)行某些任務(wù),而觸發(fā)器(Triggers)是基于某個(gè)表所產(chǎn)生的事件觸發(fā)的。

MySQL定時(shí)任務(wù)的實(shí)現(xiàn)方式有兩種:

  • 使用MySQL的event定時(shí)任務(wù)
    使用MySQL的事件計(jì)劃,首先需要在服務(wù)器開(kāi)啟event_scheduler后才能處理。
  • 使用Linux的定時(shí)任務(wù)crontab

如何開(kāi)啟事件計(jì)劃呢?

$ SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | OFF   |
+-----------------+-------+
1 row in set

如果執(zhí)行命令后返回值為OFF則表示目前事件計(jì)劃是處于關(guān)閉的狀態(tài)。

開(kāi)啟的方式也分為兩種,臨時(shí)方式使用命令行或腳本操作,永久修改則需要修改MySQL主配置文件my.ini在其中添加event_schduler=1的配置后重啟MySQL。

臨時(shí)性修改只要不重啟MySQL在當(dāng)前運(yùn)行狀態(tài)下會(huì)直接生效,一旦重啟后則失效。

$ SET GLOBAL event_scheduler = ON;
$ SET @@global.event_scheduler = ON;
$ SET GLOBAL event_scheduler = 1;
$ SET @@global.event_scheduler = 1;

事件調(diào)度器

要保證能夠執(zhí)行事件,就必須保證事件計(jì)劃是開(kāi)啟狀態(tài),事件計(jì)劃默認(rèn)為關(guān)閉狀態(tài)。

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

# 事件計(jì)劃是否開(kāi)啟
$ SHOW VARIABLES LIKE 'event%'
$ SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| event_scheduler | ON    |
+-----------------+-------+
1 row in set

# 查看事件任務(wù)是否開(kāi)啟
$ SELECT @@event_scheduler;
+-------------------+
| @@event_scheduler |
+-------------------+
| ON                |
+-------------------+
1 row in set

# 開(kāi)啟事件計(jì)劃
$ SET GLOBAL event_scheduler=1
$ SET GLOBAL event_scheduler=ON
duler=1;
Query OK, 0 rows affected

# 關(guān)閉事件計(jì)劃
$ SET GLOBAL event_scheduler=0

在真實(shí)開(kāi)發(fā)環(huán)境中會(huì)遇到MySQL服務(wù)重啟或斷電的情況,此時(shí)會(huì)出現(xiàn)事件調(diào)度器被關(guān)閉的情況。所有事件都不再起作用,解決的方式需要在MySQL的配置文件mysql.ini中加入event_scheduler=ON的配置。

事件任務(wù)

事件任務(wù)

# 查看事件任務(wù)
$ SHOW EVENTS;
Empty set

# 查看事件任務(wù)錯(cuò)誤 - 權(quán)限不足
$ SELECT * FROM mysql.event
1142 - SELECT command denied to user 'username'@'127.0.0.1' for table 'event'

# 開(kāi)啟事件任務(wù)
$ ALTER EVENT event_name ON COMPLETION PRESERVE ENABLE

# 關(guān)閉事件任務(wù)
$ ALTER EVENT event_name ON COMPLETION PRESERVE DISABLE

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

設(shè)置定時(shí)任務(wù)執(zhí)行SQL語(yǔ)句

例如:從當(dāng)日開(kāi)始每天凌晨4點(diǎn)刪除fight表超過(guò)一個(gè)月的數(shù)據(jù)

計(jì)劃任務(wù)
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

設(shè)置定時(shí)任務(wù)調(diào)用存儲(chǔ)過(guò)程

# 若計(jì)劃任務(wù)存在則刪除
DROP EVENT IF EXISTS event_name
# 創(chuàng)建計(jì)劃任務(wù)
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

參數(shù)說(shuō)明

  • ON SCHDULE schduler 定義執(zhí)行的時(shí)間和時(shí)間間隔
  • ON COMPLETION [NOT] PRESERVE 定義事件是一次性執(zhí)行還是永久執(zhí)行,默認(rèn)為一次性執(zhí)行,即NOT PRESERVE

在事件中ON SCHEDULE計(jì)劃任務(wù)中有2種設(shè)定的方式

  • 用來(lái)完成單次計(jì)劃任務(wù)。
AT 時(shí)間戳

eg:5天后
AT CURRENT_TIMESTAMP + INTERVAL 5 DAY

eg:某時(shí)間點(diǎn)
AT TIMESTAMP '2018-07-12 12:00:00'
  • 用來(lái)完成重復(fù)的計(jì)劃任務(wù)
EVERY 時(shí)間(單位)的數(shù)量 時(shí)間單位 [STARTS 時(shí)間戳] [ENDS時(shí)間戳]

eg:每隔1秒
EVERY 1 SECOND

eg:每隔10分鐘。
EVERY 10 MINUTE

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

eg:5天后開(kāi)啟每天定時(shí)處理
EVERY 1 DAY START CURRENT_TIMESTAMP + INTERVAL 5 DAY

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

在兩種計(jì)劃任務(wù)中,時(shí)間戳可以是任意的TIMESTAMPDATETIME數(shù)據(jù)類(lèi)型,時(shí)間戳需要大于當(dāng)前時(shí)間。

在重復(fù)的計(jì)劃任務(wù)中,時(shí)間(單位)的數(shù)量可以是任意非空(NOT NULL)的整數(shù)形式,時(shí)間單位是關(guān)鍵詞:YEARMONTHDAYHOURMINUTESECOND...

[ON COMPLETION [NOT] PRESERVE]

ON COMPLETION參數(shù)表示“當(dāng)這個(gè)事件不會(huì)再發(fā)生的時(shí)候”,即當(dāng)單次計(jì)劃任務(wù)執(zhí)行完畢后或當(dāng)重復(fù)性的計(jì)劃任務(wù)執(zhí)行到了ENDS階段。而PRESERVE的作用是使事件在執(zhí)行完畢后不會(huì)被DROP掉,建議使用該參數(shù),以便于查看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 '每分鐘檢測(cè)背包中換牌卡到期并每日自動(dòng)減少' 
DO 
BEGIN 
    CALL produce_knapsacks_remember_expire();
END

存儲(chǔ)過(guò)程

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 ;
-- 存儲(chǔ)過(guò)程 produce_knapsacks_remember_expire
-- 作用:判斷背包中道具記牌卡,是否過(guò)期,且每日減一。

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

錯(cuò)誤處理

出現(xiàn)錯(cuò)誤

[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' , ''));

出現(xiàn)提示

ERROR
# 在SQL中查詢(xún)計(jì)劃事件的狀態(tài)
$ SHOW VARIABLES LIKE 'event_scheduler'

# 在mysql程序的目錄下找到my.ini文件添加
$ vim my.ini
event_scheduler = 1
# 保存后重啟mysql服務(wù)

# 用腳本來(lái)實(shí)現(xiàn)
# 開(kāi)啟event_scheduler sql指令:
SET GLOBAL event_scheduler = ON;
SET @@global.event_scheduler = ON;
SET GLOBAL event_scheduler = 1;
SET @@global.event_scheduler = 1;

$ 關(guān)閉event_scheduler指令:
SET GLOBAL event_scheduler = OFF;
SET @@global.event_scheduler = OFF;
SET GLOBAL event_scheduler = 0;
SET @@global.event_scheduler = 0;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,310評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,951評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,796評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,566評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,055評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,303評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,799評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,683評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,899評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,135評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,520評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,757評(píng)論 1 282
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,528評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,844評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容