MySQL 5.1+ 內建 Event Scheduler,可替代 OS Crontab 執行資料庫層定時任務 (清理、統計、分區維護、備份觸發),優勢:事務一致性、無網路延遲、權限隔離、隨備份遷移。本文涵蓋啟用、語法、管理、監控、最佳實踐與遷移清單。
-- 運行時啟用 (重啟失效)
SET GLOBAL event_scheduler = ON;
-- 永久生效 (my.cnf)
[mysqld]
event_scheduler = ON
-- 驗證
SHOW VARIABLES LIKE 'event_scheduler';
SELECT @@event_scheduler;
CREATE EVENT [IF NOT EXISTS] event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE]
[COMMENT 'comment']
DO sql_statement;
schedule:
AT timestamp [+ INTERVAL interval] -- 一次性
| EVERY interval
[STARTS timestamp] [ENDS timestamp] -- 週期性
interval:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
-- 一次性:5 天后執行
CREATE EVENT ev_once
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 DAY
ON COMPLETION PRESERVE
DO
INSERT INTO audit_log (msg) VALUES ('One-time cleanup executed');
-- 週期性:每天 03:00 清理 30 天前日誌
CREATE EVENT ev_daily_cleanup
ON SCHEDULE EVERY 1 DAY
STARTS TIMESTAMP(CURDATE() + INTERVAL 1 DAY, '03:00:00')
ON COMPLETION PRESERVE
ENABLE
DO
DELETE FROM operation_log WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- 週期性:每月 1 號 02:00 重建統計表 (帶結束日期)
CREATE EVENT ev_monthly_stats
ON SCHEDULE EVERY 1 MONTH
STARTS '2024-01-01 02:00:00'
ENDS '2030-12-31 23:59:59'
ON COMPLETION PRESERVE
ENABLE
DO
CALL sp_rebuild_monthly_stats();
-- 修改
ALTER EVENT ev_daily_cleanup
ON SCHEDULE EVERY 1 DAY STARTS '04:00:00'
DISABLE; -- 暫停
-- 重命名
ALTER EVENT ev_daily_cleanup RENAME TO ev_daily_cleanup_v2;
-- 刪除
DROP EVENT IF EXISTS ev_daily_cleanup;
-- 查看定義
SHOW CREATE EVENT ev_daily_cleanup\G
-- 狀態列表
SHOW EVENTS FROM db_name\G
-- 或
SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA='db_name';\G
-- 最近執行狀態
SELECT EVENT_NAME, LAST_EXECUTED, STATUS, EXECUTE_AT
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'db_name';
-- 查看事件執行錯誤 (需啟用 general_log 或 slow_log)
-- 事件體內部錯誤不會自動記錄,建議在 DO 區塊包裝:
CREATE EVENT ev_safe
ON SCHEDULE EVERY 1 HOUR
DO
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @msg = MESSAGE_TEXT;
INSERT INTO event_error_log (event_name, sqlstate, msg, created_at)
VALUES ('ev_safe', @sqlstate, @msg, NOW());
RESIGNAL;
END;
CALL sp_risky_operation();
END;
| Crontab 任務 | 遷移建議 |
|---|---|
| mysqldump 備份 | 保留 Crontab (需 FLUSH LOGS、檔案系統快照、跨機傳輸) |
| 資料清理/歸檔 | ✅ 遷移至 Event (事務保護、無 SSH 依賴) |
| 統計報表聚合 | ✅ 遷移至 Event (可用 CALL Procedure 封裝複雜邏輯) |
| 分區維護 (ADD/DROP PARTITION) | ✅ 遷移至 Event (DDL 自動提交,注意鎖表) |
| 外部 API 呼叫 | ❌ 保留應用層排程 (Event 無網路能力) |
PREPARE/EXECUTE),需封裝在 Procedure 中 CALL。DISABLE 後重啟 MySQL 事件定義仍在,但 DROP 會永久刪除。DEFINER (預設建立者),建議明確 DEFINER = 'event_user'@'localhost' 並授予最小權限。system_time_zone 執行,跨時區部署請統一 UTC。結語:Event Scheduler 是資料庫原生的「無伺服器定時任務」。將純資料層維護工作 (清理、聚合、分區) 遷移至 Event,能簡化運維拓撲、提升執行可靠性、實現 Schema 級備份還原一致性。配合 ON COMPLETION PRESERVE、統一錯誤日誌、Grafana 監控 LAST_EXECUTED,打造自治的資料庫定時引擎。