前置檢查與啟用
-- 查看事件調度器狀態
SHOW VARIABLES LIKE 'event_scheduler';
-- OFF 需啟用
SET GLOBAL event_scheduler = ON;
-- 永久生效需寫入 my.cnf
[mysqld]
event_scheduler=ON
創建存儲過程示例
DELIMITER //
CREATE PROCEDURE sp_cleanup_old_logs()
BEGIN
DECLARE rows_deleted INT DEFAULT 0;
DELETE FROM operation_logs
WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
SET rows_deleted = ROW_COUNT();
INSERT INTO maintenance_log(task_name, affected_rows, exec_time)
VALUES ('cleanup_old_logs', rows_deleted, NOW());
END//
DELIMITER ;
創建定時事件
-- 每天凌晨 2:00 執行
CREATE EVENT ev_daily_cleanup
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-01 02:00:00'
DO CALL sp_cleanup_old_logs();
-- 每小時執行一次
CREATE EVENT ev_hourly_sync
ON SCHEDULE EVERY 1 HOUR
STARTS CURRENT_TIMESTAMP
DO CALL sp_sync_data();
-- 單次執行 (指定時間點)
CREATE EVENT ev_one_time
ON SCHEDULE AT '2024-12-31 23:59:59'
DO CALL sp_year_end_process();
事件管理操作
| 操作 | SQL |
| 查看事件 | SHOW EVENTS FROM db_name; |
| 啟用/禁用 | ALTER EVENT ev_name ENABLE/DISABLE; |
| 修改排程 | ALTER EVENT ev_name ON SCHEDULE EVERY 6 HOUR; |
| 刪除事件 | DROP EVENT IF EXISTS ev_name; |
| 查看定義 | SHOW CREATE EVENT ev_name; |
權限要求
- 創建事件:
EVENT 權限
- 調用存儲過程:
EXECUTE 權限
- 超級權限:
SUPER (修改全局 event_scheduler)
最佳實踐與避坑
- 時區一致性: 服務器、MySQL、應用統一使用 UTC,避免夏令時導致執行時間偏移
- 防止重複執行: 存儲過程內使用
GET_LOCK('event_name', 0) 互斥鎖
- 異常捕獲: 過程中用
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 記錄錯誤不中斷事件
- 長任務拆分: 單次執行超過 30 秒拆分為多個事件或改用外部調度 (Airflow/cron)
- 監控告警: 定期檢查
LAST_EXECUTED、STATUS,結合監控系統告警失效事件
替代方案對比
| 方案 | 優點 | 缺點 | 適用場景 |
| MySQL Event | 無外部依賴、事務一致、權限可控 | 單實例單點、無分布式協調、調試困難 | 單庫內維護任務 |
| cron + mysql client | 靈活、成熟、日誌豐富 | 需管理密碼、網絡依賴、無事務上下文 | 跨庫/跨實例任務 |
| 應用層定時任務 | 業務邏輯集中、易測試、分布式鎖 | 部署複雜、需應用常駐 | 複雜業務流程 |
| 分布式調度器 | 高可用、可視化、重試補償 | 運維成本高 | 企業級核心任務 |