{"msg":"操作成功","code":200,"data":{"createBy":"admin","createTime":"2025-03-09 14:56:32","updateBy":"admin","updateTime":"2025-03-09 14:56:32","remark":null,"id":103,"articleTitle":"MySQL（十二）定时任务EVENT","articleUrl":"mysql_event","articleThumbnail":"https://www.asumimoe.com/imgfiles/20220908/9e192744fab244d39d3b15fca035c9f7.jpg","articleFlag":"0","draftStatus":"1","reprintStatement":"0","articleSummary":"MySQL 的定时任务功能称为事件调度器（Event Scheduler），它允许您在数据库层面创建定时执行的自动化任务，类似于操作系统的 cron 任务。","articleContent":"MySQL 的定时任务功能称为 **事件调度器（Event Scheduler）**，它允许您在数据库层面创建定时执行的自动化任务，类似于操作系统的 cron 任务。\n\n## 核心概念与特点\n\n1. **基于时间调度**：\n   - 在指定时间点执行（一次性）\n   - 按固定间隔重复执行（周期性）\n   - 支持复杂的时间表达式\n\n2. **服务器端执行**：\n   - 由 MySQL 服务器直接执行\n   - 不需要外部应用程序触发\n   - 执行权限由数据库用户控制\n\n3. **任务内容**：\n   - 执行单条 SQL 语句\n   - 执行存储过程\n   - 执行包含多条语句的 BEGIN-END 块\n\n4. **事件状态**：\n   - ENABLED（默认）：激活状态\n   - DISABLED：禁用状态\n   - DISABLE ON SLAVE：在主从复制中仅在主库执行\n\n## 启用事件调度器\n\n默认情况下事件调度器是关闭的，需要显式启用：\n\n```sql\n-- 查看当前状态\nSHOW VARIABLES LIKE 'event_scheduler';\n\n-- 动态启用（服务重启后失效）\nSET GLOBAL event_scheduler = ON;\n\n-- 永久启用（需在配置文件中设置）\n# 在 my.cnf/my.ini 的 [mysqld] 部分添加：\nevent_scheduler=ON\n```\n\n## 创建事件语法\n\n```sql\nCREATE EVENT [IF NOT EXISTS] event_name\nON SCHEDULE schedule\n[ON COMPLETION [NOT] PRESERVE]\n[ENABLE | DISABLE | DISABLE ON SLAVE]\n[COMMENT 'comment']\nDO event_body;\n```\n\n#### 关键参数说明：\n\n1. **调度时间（schedule）**：\n\n   ```sql\n   -- 一次性事件\n   AT 'YYYY-MM-DD HH:MM:SS' \n   AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR\n   \n   -- 周期性事件\n   EVERY interval [STARTS timestamp] [ENDS timestamp]\n   \n   -- 示例：\n   EVERY 1 DAY                              -- 每天执行\n   EVERY 1 HOUR STARTS CURRENT_TIMESTAMP    -- 每小时执行，立即开始\n   EVERY 15 MINUTE STARTS '2025-01-01 00:00:00' ENDS '2026-01-01 00:00:00'\n   ```\n\n2. **执行后保留策略**：\n\n   - `ON COMPLETION PRESERVE`：事件执行后保留（默认周期性事件）\n   - `ON COMPLETION NOT PRESERVE`：执行后自动删除（默认一次性事件）\n\n3. **事件主体（event_body）**：\n\n   ```sql\n   -- 单条SQL语句\n   DO INSERT INTO logs(message) VALUES('Task executed');\n   \n   -- 多条语句（需使用BEGIN-END块）\n   DO BEGIN\n     UPDATE stats SET count = count + 1;\n     INSERT INTO audit_logs(action) VALUES('stats_updated');\n   END\n   \n   -- 调用存储过程\n   DO CALL cleanup_old_data();\n   ```\n\n## 事件管理命令\n\n```sql\n-- 修改事件\nALTER EVENT event_name\n[ON SCHEDULE schedule]\n[RENAME TO new_name]\n[ON COMPLETION [NOT] PRESERVE]\n[ENABLE | DISABLE]\n[COMMENT 'comment']\n[DO event_body]\n\n-- 删除事件\nDROP EVENT [IF EXISTS] event_name\n\n-- 临时禁用/启用\nALTER EVENT event_name DISABLE;\nALTER EVENT event_name ENABLE;\n\n-- 查看所有事件\nSHOW EVENTS [FROM database_name]\n\n-- 查看事件创建语句\nSHOW CREATE EVENT event_name\n\n-- 查询信息模式表\nSELECT * FROM information_schema.EVENTS\nWHERE EVENT_SCHEMA = 'your_db';\n```\n\n## 完整示例\n\n#### 示例1：每天凌晨清理旧数据\n\n```sql\nDELIMITER $$\n\nCREATE EVENT nightly_cleanup\nON SCHEDULE \n  EVERY 1 DAY \n  STARTS TIMESTAMP(CURRENT_DATE, '02:00:00') -- 每天凌晨2点\nON COMPLETION PRESERVE\nCOMMENT 'Cleanup old records'\nDO BEGIN\n  -- 删除30天前的日志\n  DELETE FROM access_logs WHERE access_time < NOW() - INTERVAL 30 DAY;\n  \n  -- 归档订单数据\n  INSERT INTO orders_archive \n  SELECT * FROM orders \n  WHERE order_date < NOW() - INTERVAL 365 DAY;\n  \n  DELETE FROM orders \n  WHERE order_date < NOW() - INTERVAL 365 DAY;\nEND$$\n\nDELIMITER ;\n```\n\n#### 示例2：每小时更新统计数据\n\n```sql\nCREATE EVENT update_stats_hourly\nON SCHEDULE EVERY 1 HOUR\nDO \n  UPDATE dashboard_stats \n  SET last_hour_count = (\n    SELECT COUNT(*) \n    FROM user_activity \n    WHERE activity_time > NOW() - INTERVAL 1 HOUR\n  );\n```\n\n#### 示例3：每月初生成报表\n\n```sql\nCREATE EVENT monthly_report\nON SCHEDULE \n  EVERY 1 MONTH \n  STARTS DATE_FORMAT(NOW(), '%Y-%m-01') + INTERVAL 1 MONTH + INTERVAL 3 HOUR -- 下个月1号凌晨3点开始执行\nDO\n  CALL generate_monthly_sales_report();\n```\n\n## 权限管理\n\n```sql\n-- 授予用户事件操作权限\nGRANT EVENT ON database_name.* TO 'username'@'host';\n\n-- 查看用户权限\nSHOW GRANTS FOR 'username'@'host';\n```\n\n## 最佳实践与注意事项\n\n1. **错误处理**：\n\n   - 事件执行错误会记录到错误日志\n\n   ```sql\n   -- 查看错误日志路径\n   SHOW VARIABLES LIKE 'log_error';\n   \n   -- Linux默认位置：/var/log/mysql/error.log\n   -- Windows默认位置：C:\\ProgramData\\MySQL\\MySQL Server\\Data\\<hostname>.err\n   ```\n\n   可增加日志详细程度\n\n   ```sql\n   [mysqld]\n   # 错误日志级别 (1=ERROR, 2=WARN, 3=INFO)\n   log_error_verbosity = 3\n   \n   # 记录警告信息\n   log_warnings = 2\n   \n   # 开启慢查询日志（记录执行超时的事件）\n   slow_query_log = 1\n   slow_query_log_file = /var/log/mysql/slow-events.log\n   long_query_time = 5  # 记录超过5秒的事件\n   ```\n\n   \n\n   - 可在事件体内使用`DECLARE HANDLER`捕获错误\n\n   ```sql\n   DO BEGIN\n     DECLARE EXIT HANDLER FOR SQLEXCEPTION\n     BEGIN\n       INSERT INTO error_logs(message) VALUES('Event execution failed');\n     END;\n     -- 业务逻辑\n   END\n   ```\n\n2. **性能优化**：\n\n   - 避免在高峰期执行资源密集型任务\n   - 对大表操作使用分批处理\n   - 确保相关表有合适的索引\n\n3. **复制环境**：\n\n   - 默认事件会在所有副本上执行\n   - 使用`DISABLE ON SLAVE`仅在主库执行\n\n   ```sql\n   CREATE EVENT replica_safe_event\n   ON SCHEDULE EVERY 1 DAY\n   DISABLE ON SLAVE\n   DO ...\n   ```\n\n4. **时间同步**：\n\n   - 确保服务器时间准确\n   - 在云环境中注意时区设置\n\n   ```sql\n   SET GLOBAL time_zone = '+8:00'; -- 设置为东八区\n   ```\n\n## 与传统方案对比\n\n| 特性     | MySQL 事件调度器 | 外部定时任务 (如 cron) |\n| -------- | ---------------- | ---------------------- |\n| 执行位置 | 数据库服务器内部 | 应用服务器             |\n| 依赖关系 | 无外部依赖       | 需维护脚本和执行环境   |\n| 权限管理 | 数据库用户权限   | 操作系统用户权限       |\n| 事务支持 | 完整事务支持     | 需额外实现             |\n| 跨平台   | 数据库平台相关   | 操作系统相关           |\n| 错误处理 | 数据库日志记录   | 需自定义日志           |\n\n","categoryId":4,"viewCount":108,"categoryName":"MySQL","author":"球接子","authorAvatar":null,"tagIds":[2,17],"tagNames":["MySQL","数据库"]}}