首页 > 数据库 > MySQL > MySQL 定时器实战:从入门到进阶
-- 查看全局状态 SHOW VARIABLES LIKE 'event_scheduler'; -- 输出结果为ON则已启用,OFF则需要开启 SET GLOBAL event_scheduler = ON;
CREATE EVENT [IF NOT EXISTS] event_name
ON SCHEDULE
schedule[ON COMPLETION [NOT] PRESERVE][ENABLE | DISABLE |
DISABLE ON SLAVE]DO event_body;
-- 其中schedule支持多种时间格式
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 }-- 创建事件 DELIMITER $$CREATE EVENT cancel_unpaid_orders ON SCHEDULE EVERY 1 MINUTESTARTS CURRENT_TIMESTAMPDOBEGINUPDATE orders SET status = 'canceled', update_time = NOW()WHERE status = 'pending'AND create_time < DATE_SUB(NOW(), INTERVAL 30 MINUTE); -- 释放库存(假设库存表通过订单ID关联) UPDATE order_items oi INNER JOIN products p ON oi.product_id = p.idSET p.stock = p.stock + oi.quantityWHERE oi.order_id IN (SELECT id FROM orders WHERE status = 'canceled'AND update_time = NOW());END$$DELIMITER ; -- 查看事件状态 SHOW EVENTS LIKE 'cancel_unpaid_orders';
-- 创建一次性事件
CREATE EVENT archive_operation_logs
ON SCHEDULE AT '2023-10-01 02:00:00'DOBEGIN
-- 创建归档表(如果不存在)
SET @archive_table = CONCAT('operation_log_', DATE_FORMAT(CURRENT_DATE - INTERVAL 1 MONTH, '%Y%m'));
SET @create_sql = CONCAT('CREATE TABLE IF NOT EXISTS ', @archive_table, ' LIKE operation_logs');
PREPARE stmt FROM @create_sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;
-- 移动数据
INSERT INTO `operation_logs_202309`
(SELECT * FROM operation_logs WHERE create_time < '2023-10-01');
DELETE FROM operation_logs WHERE create_time < '2023-10-01';END;
-- 设置事件执行后自动删除(默认会保留事件定义)
ALTER EVENT archive_operation_logs ON COMPLETION NOT PRESERVE;CREATE EVENT clean_slow_query_logsON SCHEDULE EVERY 1 DAYSTARTS '2023-09-01 00:00:00'DOBEGINDELETE FROM slow_query_logsWHERE create_time < DATE_SUB(NOW(), INTERVAL 30 DAY);-- 可选:添加重试机制(处理删除锁表问题)IF ROW_COUNT() < 0 THENRESIGNAL; -- 抛出异常,可结合错误处理机制END IF;END;
DELIMITER $$CREATE EVENT safe_transaction_eventON SCHEDULE EVERY 1 HOURDOBEGINSTART TRANSACTION;UPDATE user_balance SET balance = balance - 100 WHERE user_id = 1;-- 模拟可能失败的操作INSERT INTO transaction_record (user_id, amount) VALUES (1, -100);COMMIT;-- 错误处理(需在存储过程中使用)DECLARE EXIT HANDLER FOR SQLEXCEPTIONBEGINROLLBACK;INSERT INTO event_error_log VALUES (NOW(), 'safe_transaction_event', ERROR_MESSAGE());END;END$$DELIMITER ;
SET @table_name = CONCAT('report_', DATE_FORMAT(NOW(), '%Y%m'));
SET @sql = CONCAT('CREATE TABLE IF NOT EXISTS ', @table_name, ' (id INT PRIMARY KEY)');
PREPARE stmt FROM @sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;-- 创建事件专用用户 CREATE USER 'event_user'@'%' IDENTIFIED BY 'StrongPassword123!'; GRANT EVENT, INSERT, UPDATE, DELETE ON mydb.* TO 'event_user'@'%'; -- 指定事件使用该用户执行(需超级权限) ALTER EVENT event_name DISABLE; -- 先禁用事件 ALTER EVENT event_name OWNER TO 'event_user'@'%';ALTER EVENT event_name ENABLE;
DELETE FROM old_data LIMIT 1000;
[mysqld]log_events = ONlog_output = FILEevent_scheduler_log_file = /var/log/mysql/event_scheduler.log
-- 查看所有事件 SHOW EVENTS; -- 查看事件定义 SHOW CREATE EVENT event_name; -- 临时禁用事件(不删除定义) ALTER EVENT event_name DISABLE; -- 重新启用事件 ALTER EVENT event_name ENABLE; -- 修改执行时间(无需重建事件) ALTER EVENT event_name ON SCHEDULE EVERY 2 HOUR; -- 删除事件 DROP EVENT IF EXISTS event_name;
CREATE TABLE event_management (event_name VARCHAR(64) PRIMARY KEY,description TEXT, owner VARCHAR(32), schedule_rule VARCHAR(128), last_execute_time TIMESTAMP, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
|
场景特征 |
适合使用事件调度器 |
更适合应用层定时任务 |
|
纯数据库操作 |
✅ |
❌ |
|
跨语言 / 跨平台 |
❌ |
✅ |
|
高频率小规模任务 |
✅(<1 分钟间隔) |
❌(资源消耗大) |
|
复杂业务逻辑 |
❌(需存储过程) |
✅ |
|
分布式一致性要求 |
✅(事务支持) |
❌(需额外协调) |
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70046748/viewspace-3087602/ ,如需转载,请注明出处,否则将追究法律责任。