mysql中使用事件和儲存過程進行定時業務的執行

2021-08-09 05:12:16 字數 4102 閱讀 1027

因公司專案中有個贈送優惠券功能,此功能需求為:贈送出去的優惠券若24小時內沒有被領取,則自動設定為贈送失敗(過期未被領取),優惠券自動退換給贈送者。

初步想法是:在mysql中建立儲存過程進行業務邏輯判斷以及操作庫,然後使用事件定時的調取儲存過程,即可完成需求。

一、建立事件

1.、事件簡單描述就是可以定時的執行乙個任務,最大的優點是:一些定時操作不在依賴外部程式,而直接使用資料庫的自身提供的功能完成,可以實現每秒鐘執行乙個任務,這對一些實時性要求很高的環境就非常實用。缺點是:不可以手動呼叫,定時觸發。

2、首先檢視mysql是否開始事件

2.1 檢視資料庫是否開始事件

show variables like "event_scheduler";
查詢結果如下:

2.2 如果value = off 則需要通過如下任何乙個命令進行事件的開啟(若要關閉則為 0 或者 off):

set global event_scheduler = on;  

set @@global.event_scheduler = on;

set global event_scheduler = 1;

set @@global.event_scheduler = 1;

通過配置檔案my.conf(若要關閉則為 0 或者 off)

event_scheduler = 1 #或者on

3、建立事件event

delimiter $$

-- set global event_scheduler = on$$ -- required for event to execute but not create

create /*[definer = ]*/ event `weishop`.`e_return_conpon`

on schedule

/* uncomment the example below you want to use */

-- scheduleexample 1: run once

-- at 'yyyy-mm-dd hh:mm.ss'/current_timestamp

-- scheduleexample 2: run at intervals forever after creation

-- every 1 [hour|month|week|day|minute|...]

-- scheduleexample 3: specified start time, end time and interval for execution

/*every 1 [hour|month|week|day|minute|...]

starts current_timestamp/'yyyy-mm-dd hh:mm.ss'

ends current_timestamp/'yyyy-mm-dd hh:mm.ss' */

/*[on completion [not] preserve]

[enable | disable]

[comment 'comment']*/

every 30 minute

do begin

call p_return_coupon();

end$$

delimiter ;

4、名詞解釋: database_name:資料庫名稱

event_name:事件名稱(唯一性)

on schedule:計畫任務

schedule:決定event的執行時間和頻率(注意時間一定是將來的時間,過去的時間會報錯),有兩種形式at 和 every。

[on completion [not] preserve]:可選項,預設是 on completion not preserve 即計畫任務執行完畢自動 drop 該事

件,on completion preserve 則不會 drop 掉。 

[comment 'comment']: 可選項,注釋。

[enable||disable]:設定event的狀態,預設 enable :表示系統嘗試執行這個事件,disable:關閉改事件,可通過 

alter:命令修改。

do event_body:需要執行的sql語句,可以是復合sql,亦可以呼叫儲存過程 procedure。

我們在上面建立了乙個event,每隔30分鐘呼叫一次 p_return_coupon 儲存過程。

二、建立儲存過程 p_return_coupon

1、儲存過程的介紹:簡單來說,儲存過程就是為以後的使用而儲存的一條或者多條mysql語句的集合,儲存過程中有業務邏

輯和流程的集合,可以在儲存過程中建立表,更新資料,刪除等等。

2、為什麼需要使用儲存過程:

2.1、通過把複雜的業務封裝成乙個單元,簡化操作,程式中只需要 呼叫儲存過程處理,比起單條 sql 執行,**量和效

率會有所改善。

2.2、在生產環境可以直接修改儲存過程來處理bug,不需要重啟伺服器(前提是修改的儲存過程需要進行詳細的測試)。

2.3、方便業務的變更維護,如果表明和列名發生變化,只需要修改儲存過程,不用改變任何**。

3、建立儲存過程

delimiter $$

create

/*[definer = ]*/

procedure `weishop`.`p_return_coupon`()

/*language sql

| [not] deterministic

| | sql security

| comment 'string'*/

begin

-- 宣告乙個標誌done,用來判斷游標是否遍歷完成

declare done int default 0;

-- 宣告乙個變數,用來存放從游標中提取的資料

declare cid int;

declare ctime datetime;

-- 宣告乙個游標

declare cur cursor for select m.id from member_coupon m inner join given_record g on m.id = g.coupon_id where m.status = 3 and g.orders = 1 and g.create_date is not null;

-- 在游標迴圈到最後會將 done 設定為 1(如果不加該行 游標為空的時候 就會報錯)

declare continue handler for not found set done = 1;

-- 開啟游標

open cur;

-- 開始迴圈

repeat

-- 游標的每一次迴圈值賦值給cid變數

fetch cur into cid;

-- 如果游標沒有結束

if not done then

-- 根據cid將找到的create_date賦值給ctime變數

select create_date into ctime from given_record where orders = 1 and coupon_id = cid;

-- 如果ctime變數加上5分鐘小於當前時間則進行更新操作

if date_add(ctime, interval 5 minute)< now() then

update member_coupon set status = 1 where status = 3 and id = cid;

update given_record set orders = 3 where orders = 1 and coupon_id = cid;

end if;

end if;

until done end repeat;

close cur;

end$$

delimiter ;

4、其中使用到了游標 cursor 和 迴圈 repeat,我們下節進行描述。

三、結束語:這樣的話就可以通過事件每隔30分鐘呼叫儲存過程來處理若5分鐘未被領取則歸還贈送者業務!

歡迎指正。

mysql儲存過程中使用事件

create definer root localhost procedure createbusiness parameter1 int begin routine body goes here.declare flag int default parameter1 宣告變數flag,將引數值賦給...

mysql儲存過程中使用事務

mysql儲存過程中使用事務 1 drop procedure ifexists test sp1 2create procedure test sp1 3begin 4declare t error integer default 0 5declare continue handler for s...

儲存過程中使用事務

create procedure updatewanjun username nvarchar 500 userpassword nvarchar 500 returnval int output as set xact abort on begin transaction t update adm...