一、MySQL 定时事件(EVENT)应用总结
1. 核心作用
MySQL 事件是数据库内置定时任务,无需借助 Linux crontab、Windows 计划任务等外部工具,可直接在库内定时执行 DML/DDL 语句,常用于:
- 过期数据自动清理(日志、实时采集、历史工况表);
- 定时统计汇总报表、生成日 / 月统计数据;
- 定时更新状态、重置临时标记;
- 自动归档、迁移冷热数据。
2. 关键特性
- 调度规则:支持按分钟 / 小时 / 天 / 月循环,也可指定单次定点执行;
- 持久属性
ON COMPLETION PRESERVE:循环定时任务,执行完保留事件,下次继续运行;ON COMPLETION NOT PRESERVE:一次性任务,执行完成自动删除事件;
- 开关依赖 :全局参数
event_scheduler=ON才能生效,重启数据库会重置,需配置配置文件永久开启; - 执行身份:以创建事件的用户权限运行,用户权限不足会执行失败;
- 事务特性 :
BEGIN...END代码块内多条语句为一个上下文,大批量删除建议分批,避免锁表、阻塞业务。
3. 适用场景 & 优缺点
适用场景
- 业务采集海量时序数据(OEE、设备实时数据、传感器日志),需定期清理过期数据;
- 轻量定时统计,不想额外部署定时脚本;
- 数据库自闭环运维,减少外部调度依赖。
优点
- 原生内置,无额外服务部署;
- 与数据库事务、索引天然适配;
- 建表、建事件脚本可统一版本管理。
缺点
- 仅库内操作,无法调用外部程序、接口;
- 大批量删除易产生大事务,影响线上读写性能;
- 调度器关闭后任务暂停,无告警机制,需自行监控。
4. 生产使用规范
- 循环定时必须使用
PRESERVE; - 大表删除禁止一次性全删,采用 LIMIT 分批删除;
- 时间过滤字段建立索引,提升删除效率;
- 增加注释说明用途、执行时间;
- 创建时加
IF NOT EXISTS防止重复创建报错; - 上线前确认
event_scheduler已永久开启。
二、带完整注释优化版定时清理事件 + 功能说明
完整带注释 SQL
sql
-- 创建每日清理历史数据定时事件,不存在才创建,避免重复创建报错
CREATE EVENT IF NOT EXISTS cleanup_realtime_1d
-- 调度规则:每1天执行一次
ON SCHEDULE EVERY 1 DAY
-- 首次启动执行时间:2025-12-22 早上08:30,之后每日08:30自动运行
STARTS '2025-12-22 08:30:00.000'
-- 循环任务:执行完成后保留事件,保证第二天继续执行
ON COMPLETION PRESERVE
-- 创建后默认启用该定时事件
ENABLE
-- 事件注释:记录用途,方便后期维护查看
COMMENT '每日08:30分批清理oee_data_history表1天前的过期时序数据,避免一次性大量删除锁表'
DO
BEGIN
-- 循环判断:表中是否存在超过1天的过期数据,有则持续删除
WHILE EXISTS (SELECT 1 FROM oee_data_history WHERE _TIMESTAMP < DATE_SUB(NOW(), INTERVAL 1 DAY)) DO
-- 每次仅删除1000条,拆分大事务,降低数据库锁竞争、减少binlog压力
DELETE FROM oee_data_history WHERE _TIMESTAMP < DATE_SUB(NOW(), INTERVAL 1 DAY) LIMIT 1000;
-- 删除一次休眠0.1秒,给数据库IO、业务读写留出缓冲时间,防止CPU/IO打满
SLEEP 0.1;
END WHILE;
END;
程序整体功能说明
- 定时规则 每天早上 08:30 自动触发执行,首次执行从
2025-12-22 08:30开始,永久循环执行。 - 数据清理逻辑 针对
oee_data_history设备 OEE 历史数据表,删除时间戳_TIMESTAMP早于当前时间 1 天的历史采集数据,只保留近 1 天数据。 - 性能优化逻辑 不一次性删除全部过期数据,采用循环分批删除,每次最多删 1000 条,每轮删除后短暂休眠,缓解数据库压力,避免大批量删除造成表锁、业务查询卡顿、大量日志写入。
- 容错与维护设计
- 使用
IF NOT EXISTS重复执行脚本不会报错; - 添加注释记录用途,方便运维排查;
PRESERVE保证循环任务不会执行一次就消失;- 代码块闭合完整,语法无缺陷。
- 使用
- 使用前提 MySQL 全局事件调度器
event_scheduler必须开启,且_TIMESTAMP字段需建立索引加速过滤删除。