事件可以指定单次或以一定的间隔执行 SQL 代码。通常是将复杂的 SQL 语句使用存储过程封装好,然后周期性地调用存储过程完成一定的任务。

事件无需建立服务端连接,而是通过一个独立的事件调度器线程完成初始化。事件没有输入参数也没有返回值,这是因为没有连接也就不存在输入和输出了。启用后,可以通过服务端日志查看执行的指令,但是很难知道具体来自哪个事件。也可以查询 INFORMATION_SCHEMA.EVENTS 表了解事件的状态,例如最近一次执行的时间。

与存储过程类似,事件也需要考虑类似的问题。首先,事件增加了 MySQL 服务端额外的工作。虽然事件本身的负荷很小,但是事件调用的 SQL 语句可能对性能产生严重的影响。另外,事件也会有存储过程那样基于语句的复制带来的那一类问题。事件比较好的应用是做诸如周期性的维护任务、重建缓存、数据统计、保存监测和诊断的状态值等任务。

下面的例子创建了一个事件,调用存储过程每周对指定的数据库运行数据表优化:

CREATE EVENT optimize_somedb ON SCHEDULE EVERY 1 WEEKDO CALL optimize_tables('somedb');
CREATE EVENT optimize_somedb ON SCHEDULE EVERY 1 WEEKDO BEGINDECLARE CONTINUE HANDLER FOR SQLEXCEPTION  BEGIN END;  IF GET_LOCK('somedb', 0) THEN  DO CALL optimize_tables('some_db');  END IF;  DO RELEASE_LOCK('somedb');END

虽然事件与连接无关,但是却是与线程有关的。MySQL 服务端有一个主事件调度线程,可以通过在服务端配置中开启:

SET GLOBAL event_handler := 1;

虽然事件调度器是单线程的,但是事件本身是可以并发执行的。每次事件执行的时候服务端会创建新的进程。在事件内部,可以调用 CONNECTION_ID()获取一个唯一的值(虽然实际没有连接),实际返回的就是线程 id。进程和线程在事件执行完后会销毁。可以通过 SHOW PROCESSLIST 查看,在 Command 列中会显示为 Connect。

虽然,进程创建了实际执行事件的线程,但线程在事件完成后会销毁,并不会放入缓存中,因此 Threads_created 这个状态计数器并不会看到增加。

结语:事件与应用程序、或操作系统级的定时任务相比,由于没有了 SQL 连接建立的过程,因此效率会更高,而且开销不大。适用于需要周期性运行的 SQL 脚本任务,例如数据表优化、生成统计报表数据等等。但是,需要注意,事件本身可能存在并发问题,这个可以通过加锁解决。同时,如果事件需要重复执行,最好是不要执行过于复杂耗时的任务。

更多相关文章

  1. vue 基础语法及购物车小案例
  2. Android(安卓)之 AsyncTask 异步任务
  3. Android(安卓)任务和回退堆栈---启动任务
  4. [android]在上下文菜单的选中事件中获取列表选中的元素
  5. android 多点触控
  6. Android解决父控件拦截子控件手势滑动事件的问题
  7. Android下模拟按键输入
  8. android touch事件解析
  9. Android(安卓)后台任务(五)Service

随机推荐

  1. Canvas 动画的性能优化实践
  2. 《趣说前端 - 002 》— 两种作用域模型介
  3. 贞炸了!上线之后,消息收不到了!
  4. 【干货】BAT大佬告诉你如何埋点
  5. Vuex 注入 Vue 生命周期的过程
  6. 熔断器 Hystrix 源码解析 —— 请求执行(
  7. 数据库读写分离这个坑,让刚入职的我一脸懵
  8. 学习C第二天-字符串
  9. centos 磁盘管理与维护
  10. 【前端词典】arr.filter(parseInt) 考查