1. 程式人生 > >MySQL job/定時任務/event 學習筆記

MySQL job/定時任務/event 學習筆記

由於週末做的資料遷移過程中,對遷移時間段內產生的資料及之後新產生的資料沒有做到資料遷移,所以我寫了個job讓系統定時任務的跑到我的一張臨時表,之後通過程式處理資料實現不同獨立的資料庫之間的資料同步。

 

程式程式碼就不做記錄,可以用Java、python等都能實現,這次筆記主要記錄MySQL event的使用;

 

MySQL的定時任務(簡稱job)是可以通過MySQL自身實現的,相比較系統的計劃任務,MySQL自身job可以實現秒級定位,即可以精確到秒單位進行任務的執行(系統計劃任務一般是分鐘);所以MySQL的job在要求精確化的任務上有極大的優勢;MySQL 的job官方稱為event,MySQL EVENT的原理和觸發器非常的相似,區別在於,MySQL的event是系統定時驅動執行,而觸發器是通過需求觸發進行執行的,兩者各有優勢。

MySQL event和觸發器一樣可以呼叫儲存過程,然而儲存過程不能呼叫event,event只能系統執行,對於執行需求變更,我們只能手動的去調整event。

建立語法:

--------建立語法
CREATE 
    [DEFINER = { user | CURRENT_USER }] --一般不寫
    EVENT --event標識
    [IF NOT EXISTS] --如果沒有就新建,建議不寫這一行,確保每個event獨立不衝突
    event_name -- 取個event名字
    ON SCHEDULE --計劃任務標識
    schedule --計劃任務時間,有兩個引數(at 和 every),at代表當前一次,every表示每過多少時間執行一次
    [ON COMPLETION [NOT] PRESERVE] --可以不寫,預設是ON COMPLETION NOT PRESERVE 即計劃任務執行完畢後自動drop該事件;ON COMPLETION  PRESERVE則不會drop
    [ENABLE | DISABLE | DISABLE ON SLAVE] --可以不寫,預設狀態,預設是啟用狀態,可以指定為新建關閉狀態 
    [COMMENT 'comment'] --註釋event,可以不寫
    DO --執行語句標識
    event_body; --執行的sql
 


--------------------------------------------計劃任務可以定義的時間方式:
schedule: 
    AT timestamp [+ INTERVAL interval] ... --at方式
  | EVERY interval                         --every方式
    [STARTS timestamp [+ INTERVAL interval] ...] --在at/every後可以指定什麼時候開始
    [ENDS timestamp [+ INTERVAL interval] ...]  --指定什麼時候結束

-------------------------------------------MySQL官方提供的時間字元,可以參考   
interval: 
    quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | 
              WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE | 
              DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND} 

本次我的語法是:


CREATE EVENT 
ev_db_custinfo_sync 
ON SCHEDULE 
EVERY 1 DAY 
ON COMPLETION PRESERVE 
DO
INSERT INTO db_cust_sync.t_dq_user ( CustID, DeviceNo ) SELECT
s.cust_id,
s.loginname 
FROM
	jf_custdb.t_cust_info s 
WHERE
	s.logintype = '18' 
	AND s.create_time > DATE_SUB( CURDATE( ), INTERVAL 1 DAY ) 
	AND NOT EXISTS ( SELECT 1 FROM db_cust_sync.t_dq_user l WHERE l.CustID = s.cust_id );

我定義每天跑一次,當然我偷懶了一下,理論上定義起始時間在晚上最好,然後由於壓力不大,我就沒有定義起始時間了,如果對於資料庫優化,建議考慮寫個起始時間儘量減少資料庫對業務產生的壓力。

 

在建立job之前,需要做以下幾件事:

1、確保系統的event事件開關是開啟的,允許我們建立event;

2、確保我們建立後是在成功執行的,所以要會檢視當前系統有的event

3、確保我們建立是按照需求來的,如果需要更改,我們要會更改event

 

逐步記錄:

1、檢視系統開關:

-- 方法一
select @@event_scheduler;

--方法二
show variables like 'event_scheduler';

以上語句都可以,隨你選擇,執行結果如下:

如果value是off或者是0;代表沒有開啟,我們可以手動開啟:

-- 開啟event事件:
-- 方法1
set GLOBAL event_scheduler=ON;
-- 方法2
set GLOBAL event_scheduler=1;

當然關閉就是反過來,只有在確保event全域性可用的情況下我們才能建立event;

 

2、建立event之前,看看系統存在哪些:

-- 檢視系統有哪些event事件
--方法一
select * from mysql.event;

--方法二
SELECT * FROM information_schema.events;

建立過程開頭已記錄,在建立完後也可以通過語句核實建立的event,執行結果如下:

 

3、調整,變更event:

--完整修改:
ALTER EVENT event_name
ON SCHEDULE schedule
ON COMPLETION [NOT] PRESERVE
RENAME TO new_event_name
ENABLE | DISABLE
DO
  event_body


----------------------------------------------單獨修改一些資料:
-- 修改時間
ALTER EVENT ev_custinfo_sync ON SCHEDULE EVERY 1 DAY;


--修改do執行語句
ALTER EVENT ev_custinfo_sync
do
INSERT INTO db_cust_sync.t_dq_user ( CustID, DeviceNo ) SELECT
s.cust_id,
s.loginname 
FROM
	jf_custdb.t_cust_info s 

--修改可用(啟用/禁用)
ALTER EVENT ev_custinfo_sync
DISABLE;

--重新命名這個event:
ALTER EVENT ev_custinfo_sync RENAME TO db_cust_sync_event

--如果event建立的時候有指定庫,想移動到其他庫:
ALTER EVENT cust_info_db.ev_custinfo_sync RENAME TO  cust_sync_db.ev_custinfo_sync

-------------------------------------------------------------------------------
--刪除這個event
DROP EVENT ev_custinfo_sync

以上所有修改引數都是要基於當前存在於該event的情況下,所以在修改前,最好先show一下;

 

趟過的坑:

1、預設建立的event是在當前位置所在的庫,event可以指定所在庫的,所以,騷年們,如果其他庫要用,請指定下或者移動下。event需要指定一個庫,不指定會建立報錯的;

 

2、異常排查,如果在event測試中,發現測試資料沒有存在或者執行,請單獨跑一次do後面的執行體,有時候不是event出問題了,而是do後面的執行體sql本身就沒有資料,所以event沒有反應;

 

3、如果定義兩個event在同一時間同一秒鐘執行,會衝突,所以請至少間隔一秒;

 

4、如果只是執行select不做什麼動作(匯出,變更等操作),系統是不會儲存資料的,所以只是select你會發現啥也沒有,並不是event沒有執行。

 

5、on completion引數最好寫下,指定引數為preserve,這項引數會讓event記錄一直存在於,如果不帶這項引數,預設是drop屬性,意為著執行完後就drop掉,很多情況就像是沒有建立一樣。