MySQL 5.1+ 內建 **Event Scheduler**(事件調度器),可在資料庫層面實現定時執行 SQL、存儲過程、清理數據等任務,**無需依賴系統 crontab 或應用層排程器**。本文系統講解語法、配置、常見場景與最佳實踐。
檢查狀態:
SHOW GLOBAL VARIABLES LIKE 'event_scheduler'; SELECT @@event_scheduler; -- OFF / ON / DISABLED
永久啟用(my.cnf):
[mysqld] event_scheduler = ON
臨時啟用(重啟失效):SET GLOBAL event_scheduler = ON;
CREATE [DEFINER = {user | CURRENT_USER}]
EVENT [IF NOT EXISTS] 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}
CREATE EVENT test_once
ON SCHEDULE AT '2025-12-31 23:59:59'
COMMENT '年終歸檔一次性任務'
DO INSERT INTO archive_log (msg) VALUES ('Year-end archive');
CREATE EVENT daily_stats
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP + INTERVAL 1 DAY -- 明天開始
DO
INSERT INTO daily_summary (stat_date, total_users)
SELECT CURDATE(), COUNT(*) FROM users;
DELIMITER //
CREATE EVENT complex_cleanup
ON SCHEDULE EVERY 1 HOUR
DO BEGIN
DECLARE v INT DEFAULT 0;
WHILE v < 5 DO
DELETE FROM temp_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 7 DAY) LIMIT 1000;
SET v = v + 1;
END WHILE;
INSERT INTO cleanup_log (run_time, rows_affected) VALUES (NOW(), ROW_COUNT());
END//
DELIMITER ;
CREATE EVENT limited_run ON SCHEDULE EVERY 12 HOUR STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS CURRENT_TIMESTAMP + INTERVAL 4 WEEK DO CALL refresh_materialized_view();
| 操作 | SQL |
|---|---|
| 查看所有事件 | SELECT * FROM information_schema.EVENTS; |
| 啟用事件 | ALTER EVENT schema.event_name ENABLE; |
| 禁用事件 | ALTER EVENT schema.event_name DISABLE; |
| 刪除事件 | DROP EVENT [IF EXISTS] schema.event_name; |
| 修改排程 | ALTER EVENT e ON SCHEDULE EVERY 6 HOUR; |
CREATE EVENT db_name.event_name,備份/遷移時需包含 information_schema.EVENTS 或用 mysqldump --events。EVENT 權限;DEFINER 需 SUPER 權限指定他用戶。system_time_zone),跨時區部署請統一 UTC。DISABLE ON SLAVE,主從切換後需手動 ENABLE。GET_LOCK() 互斥。-- 查看最近執行狀態
SELECT EVENT_NAME, LAST_EXECUTED, STATUS FROM information_schema.EVENTS;
-- 事件執行錯誤不會寫入 error log,建議在事件體內 INSERT 記錄執行日志
CREATE EVENT monitored_task
ON SCHEDULE EVERY 1 MINUTE
DO INSERT INTO task_log (event_name, run_time, status)
VALUES ('monitored_task', NOW(), 'START');
-- 實際業務邏輯...
-- 最後 UPDATE task_log SET status='SUCCESS' WHERE ...
| 維度 | MySQL Event | Linux crontab | 應用層 |
|---|---|---|---|
| 部署耦合度 | 低(隨庫遷移) | 中(依賴主機) | 高(代碼部署) |
| 事務一致性 | 弱(自動提交) | 無 | 強(可控) |
| 監控可視化 | 需自建日志表 | 系統日志 | APM/日志平台 |
| 適合場景 | 數據歸檔、統計刷新、分區維護 | OS 級備份、腳本 | 業務流程、外部 API 調用 |
MySQL Event Scheduler 是**資料庫內部周期性維護任務**的首選:備份統計、分區管理、歷史數據清理、物化視圖刷新。業務邏輯、外部調用、強事務場景仍建議在應用層處理。