Mysql中event事件的入門
主要涉及的知識點:mysql的存儲過程、mysql的event事件調度。
參考資料:
Qiao_Zhi的博客:【周期性執行事件】MySQL事件(Event)&任務調度。
起風了的博客:mysql存儲過程查詢結果循環遍歷 判斷 賦值 游標等基本操作。
webbc的文章:MySQL游標概念與用法詳解。
萊克星頓的槍聲的博客:mysql游標的用法及作用。
阿凱--Nonkey的博客:MySql 游標的使用(二)FETCH INTO取出來的部分字段為NULL。
qq564392180的博客:Mysql Event Scheduler不執行。
直接示例:
假如要實現這樣一個場景,購買訂單生成后,三十分鍾未支付,自動更新訂單狀態,並返還商品庫存。
存儲過程示例:
delimiter // DROP PROCEDURE IF EXISTS `updateOrderStatus` // CREATE PROCEDURE updateOrderStatus() BEGIN DECLARE order_id int DEFAULT 0; DECLARE goods_id int DEFAULT 0; DECLARE done int DEFAULT 0; DECLARE overtime_order CURSOR FOR select id,shop_id from `order` where `status`='等待支付' and `order_time`<=(unix_timestamp(now())-1800); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; OPEN overtime_order; read_loop:LOOP FETCH overtime_order into order_id,goods_id; if done = 1 THEN leave read_loop; END IF; update `order` set `status` = '未支付',order_end_time=now() where `id`=order_id; update `shop` set `num` = `num`+1 where `id`=goods_id; END LOOP; CLOSE overtime_order; END // delimiter ;
event事件調度示例:
drop event if exists event_update_order; CREATE event event_update_order ON SCHEDULE EVERY 1 MINUTE DO CALL updateOrderStatus();
知識點:
(1)修改sql默認的以【分號;】結束為【//】: delimiter //
(2) 創建存儲過程前先查看下是否已存在:show create procedure updateOrderStatus;
或存在先刪除:DROP PROCEDURE IF EXISTS `updateOrderStatus`;
(3)創建event事件前先查看下是否已存在:show create event event_update_order;
或存在先刪除:drop event if exists event_update_order;
(4)mysql的event事件調度程序默認是關閉的。
查看event是否開啟:
mysql> SHOW VARIABLES LIKE 'event_scheduler';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | OFF |
+-----------------+-------+
1 row in set (0.01 sec)
開啟:
SET GLOBAL event_scheduler=on;
(5)存儲過程中定義的變量不能和數據表中的字段名重名,不然取不到值。
(6)查看調度器線程:show processlist;
(7)在存儲過程中這樣定義變量:DECLARE order_id int DEFAULT 0;
(8)當存在多個數據需要循環時,可以用到游標,
//創建游標,並存儲數據
declare user_data CURSOR for
select id,name from user where id<10;
//創建變量,標識游標是否結束
declare done INT DEFAULT 0;
//當游標中的內容執行完后將done設置為1,說明循環游標結束
declare CONTINUE HANDLER FOR NOT FOUND SET done=1;
//打開游標
open user_data;
//執行循環
read_loop:LOOP
//判斷是否結束循環
IF done=1 THEN
LEAVE read_loop;//跳出循環
END IF;
//取游標中的值
FETCH user_data into user_id,user_name;
//執行增刪改查操作
insert ...;
delete ...;
update ...;
select ...;
END LOOP read_loop;
//釋放游標
CLOSE user_data;