啟用事件調度器
-- 查看狀態
SHOW VARIABLES LIKE 'event_scheduler';
-- OFF / ON / DISABLED
-- 動態啟用(重啟失效)
SET GLOBAL event_scheduler = ON;
-- 永久生效:my.cnf [mysqld] 區段加入
event_scheduler = ON
建立事件
CREATE EVENT IF NOT EXISTS `daily_cleanup_logs`
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR
ON COMPLETION PRESERVE
ENABLE
COMMENT '清理 30 天前的操作日誌'
DO
DELETE FROM `sys_logs` WHERE `created_at` < DATE_SUB(NOW(), INTERVAL 30 DAY);
排程類型對照
| 語法 | 說明 | 範例 |
| AT timestamp | 單次執行 | AT '2024-12-31 23:59:59' |
| EVERY interval | 週期執行 | EVERY 30 MINUTE、EVERY 1 WEEK |
| STARTS / ENDS | 生效時間窗 | STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR |
管理事件
-- 修改排程/狀態
ALTER EVENT `daily_cleanup_logs`
ON SCHEDULE EVERY 6 HOUR
DISABLE;
-- 重命名
ALTER EVENT `daily_cleanup_logs` RENAME TO `cleanup_logs_6h`;
-- 臨時禁用/啟用
ALTER EVENT `cleanup_logs_6h` DISABLE;
ALTER EVENT `cleanup_logs_6h` ENABLE;
-- 刪除
DROP EVENT IF EXISTS `cleanup_logs_6h`;
查看事件資訊
-- 列出所有事件
SHOW EVENTS;
-- 查看建立語句
SHOW CREATE EVENT `daily_cleanup_logs`;
-- 詳細元數據
SELECT * FROM INFORMATION_SCHEMA.EVENTS
WHERE EVENT_SCHEMA = 'my_db' AND EVENT_NAME = 'daily_cleanup_logs';
實戰範例:每 30 分鐘歸檔熱門文章狀態
CREATE EVENT `archive_hot_articles`
ON SCHEDULE EVERY 30 MINUTE
DO
UPDATE `jd_article`
SET `status` = 0
WHERE `status` = 1
AND `publish_time` <= NOW() - INTERVAL 7 DAY;
注意事項與坑點
- ⚠️ 事件執行權限取決於
DEFINER,建議使用具備所需權限的專用帳號。
- ⚠️
ON COMPLETION NOT PRESERVE(預設)單次事件執行後自動刪除,週期事件不受影響。
- ⚠️ 時區一致性:
SHOW VARIABLES LIKE 'time_zone'; 確保服務器與應用時區一致。
- ⚠️ 長時間運行的事件可能阻塞
event_scheduler 執行緒,複雜邏輯建議放入存儲過程異步處理。
替代方案對比
| 方案 | 優點 | 缺點 |
| MySQL Event | 資料庫內建、無外部依賴、權限可控 | 無分散式調度、調試不便、高併發下可能阻塞 |
| Linux cron + 腳本 | 靈活、成熟、支援多語言 | 需維護連線資訊、網路故障需自行重試 |
| 應用層排程器 | 業務邏輯集中、易測試、支援分散式鎖 | 增加部署複雜度 |