替代 Linux Crontab 的原生定時任務方案:無外部依賴、單機多實例自動隔離、隨數據庫備份遷移、權限體系統一。適用於數據歸檔、統計聚合、緩存預熱、異步清理等場景。
CREATE EVENT event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO event_body;
schedule:
AT timestamp [+ INTERVAL interval] ... -- 單次執行
| EVERY interval
[STARTS timestamp [+ INTERVAL interval] ...]
[ENDS timestamp [+ INTERVAL interval] ...] -- 循環執行
interval:
quantity {YEAR|QUARTER|MONTH|DAY|HOUR|MINUTE|WEEK|SECOND
|YEAR_MONTH|DAY_HOUR|DAY_MINUTE|DAY_SECOND
|HOUR_MINUTE|HOUR_SECOND|MINUTE_SECOND}
AT '2024-01-01 00:00:00' 固定時間AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR 1 小時後EVERY 1 DAY 每天執行,創建即執行首次EVERY 3 DAY STARTS '2024-01-01 00:00:00' 指定首次時間EVERY 1 MONTH STARTS CURRENT_TIMESTAMP + INTERVAL 10 MINUTE ENDS '2024-12-31 23:59:59' 完整窗口控制SET GLOBAL event_scheduler = ON; -- 即時生效 SELECT @@event_scheduler; -- 驗證狀態
[mysqld] event_scheduler = ON
| 值 | 含義 | 動態修改 |
|---|---|---|
| OFF / 0 | 關閉(默認) | ✅ 可切換 ON |
| ON / 1 | 啟用 | ✅ 可切換 OFF |
| DISABLED | 禁用,線程不啟動 | ❌ 僅啟動時指定,運行期不可變 |
-- 簡單 SQL
CREATE EVENT e_hourly
ON SCHEDULE EVERY 1 HOUR
COMMENT '清理過期 Session'
DO DELETE FROM sessions WHERE updated_at < NOW() - INTERVAL 1 DAY;
-- 複雜邏輯(需 DELIMITER)
DELIMITER //
CREATE EVENT e_complex
ON SCHEDULE EVERY 5 SECOND
DO
BEGIN
DECLARE v INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
WHILE v < 5 DO
INSERT INTO t1 VALUES (0);
UPDATE t2 SET s1 = s1 + 1;
SET v = v + 1;
END WHILE;
END //
DELIMITER ;
ALTER EVENT e_hourly
ON SCHEDULE EVERY 30 MINUTE
DISABLE
RENAME TO e_half_hour;
DROP EVENT IF EXISTS e_old;
SHOW EVENTS; SHOW CREATE EVENT e_hourly; SELECT * FROM information_schema.events WHERE event_schema = 'mydb'; SELECT * FROM mysql.event;
LOCK TABLES、LOAD DATA、INSERT DELAYED(無效)SELECT/SHOW(結果無法獲取),改用 SELECT ... INTOALTER EVENT(創建成功但執行報錯)GET_LOCK('event_name', 0) 或表鎖/行鎖互斥time_zone 固化為 UTC 存儲,跨時區遷移需注意sql_mode 綁定執行期,避免隱式類型轉換差異-- 存儲過程:每行 id2 增加 2
DROP PROCEDURE IF EXISTS sp_add_two;
DELIMITER //
CREATE PROCEDURE sp_add_two()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_id INT;
DECLARE cur CURSOR FOR SELECT id FROM test;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
REPEAT
FETCH cur INTO v_id;
IF NOT done THEN
UPDATE test SET id2 = id2 + 2 WHERE id = v_id;
END IF;
UNTIL done END REPEAT;
CLOSE cur;
END //
DELIMITER ;
-- 事件:每天凌晨執行,持續 40 天
CREATE EVENT ev_daily_add
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-01 00:00:00'
ENDS '2024-02-10 00:00:00'
ON COMPLETION PRESERVE
DO CALL sp_add_two();