MySQL 使用事件(Events)完成计划任务


Posted in MySQL onMay 24, 2021

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

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

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

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

CREATE EVENT optimize_somedb ON SCHEDULE EVERY 1 WEEK
DO 
CALL optimize_tables('somedb');

可以指定事件是否需要重复执行。在某些情况下是没问题的,但是有些情况则不行。以上面的例子为例,你也许是想在所有的副本上运行 OPTIMIZE TABLE 指令。但是,需要知道的是如果是全部副本都同时执行这个操作的话,这会影响整个服务端性能(例如锁表)。 而且,周期性事件可能会花很长事件才能完成,甚至有可能下一个事件还没结束新的事件就又开始执行了。MySQL 不会阻止这样的情况,因此需要自己写代码实现相同任务的互斥。可以使用加锁的方式达到这一目的:

CREATE EVENT optimize_somedb ON SCHEDULE EVERY 1 WEEK
DO 
BEGIN
	DECLARE 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

看起来“多余”的 continue handler 可以保证即便是发生了异常也会释放锁。

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

SET GLOBAL event_handler := 1;

一旦启用,这个线程会执行指定调度的事件。可以通过查看服务端的错误日志来了解事件执行的信息。

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

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

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

以上就是MySQL 使用事件(Events)完成计划任务的详细内容,更多关于MySQL 用事件完成计划任务的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
详解Mysql和Oracle之间的误区
May 18 MySQL
IDEA 链接Mysql数据库并执行查询操作的完整代码
May 20 MySQL
MySQL系列之十四 MySQL的高可用实现
Jul 02 MySQL
MySQL基础快速入门知识总结(附思维导图)
Sep 25 MySQL
MySQL中的引号和反引号的区别与用法详解
Oct 24 MySQL
MySQL 开窗函数
Feb 15 MySQL
Mysql分库分表之后主键处理的几种方法
Feb 15 MySQL
MySQL七大JOIN的具体使用
Feb 28 MySQL
关于MySQL临时表为什么可以重名的问题
Mar 22 MySQL
数据分析数据库ClickHouse在大数据领域应用实践
Apr 03 MySQL
MySQL数据库实验实现简单数据库应用系统设计
Jun 21 MySQL
MySQL 原理优化之Group By的优化技巧
Aug 14 MySQL
MySQL触发器的使用
May 24 #MySQL
MySQL 重命名表的操作方法及注意事项
May 21 #MySQL
Mysql官方性能测试工具mysqlslap的使用简介
May 21 #MySQL
MySQL官方导出工具mysqlpump的使用
May 21 #MySQL
新手必备之MySQL msi版本下载安装图文详细教程
MySQL数据库压缩版本安装与配置详细教程
MySQL 8.0 之不可见列的基本操作
May 20 #MySQL
You might like
基于mysql的bbs设计(五)
2006/10/09 PHP
解析smarty 截取字符串函数 truncate的用法介绍
2013/06/20 PHP
PHP获取客户端真实IP地址的5种情况分析和实现代码
2014/07/08 PHP
js常用函数 不错
2006/09/08 Javascript
Javascript 文件夹选择框的两种解决方案
2009/07/01 Javascript
File, FileReader 和 Ajax 文件上传实例分析(php)
2011/04/27 Javascript
js两行代码按指定格式输出日期时间
2011/10/21 Javascript
js操作模态窗口及父子窗口间相互传值示例
2014/06/09 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
JS中对象与字符串的互相转换详解
2016/05/20 Javascript
jquery获取input type=text中的值的各种方式(总结)
2016/12/02 Javascript
AngularJS使用ng-class动态增减class样式的方法示例
2017/05/18 Javascript
JS解析url查询参数的简单代码
2017/08/06 Javascript
Echarts之悬浮框中的数据排序问题
2018/11/08 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【圆形情况】
2018/12/13 Javascript
node学习笔记之读写文件与开启第一个web服务器操作示例
2019/05/29 Javascript
layui表格内放置图片,并点击放大的实例
2019/09/10 Javascript
[42:36]DOTA2上海特级锦标赛B组败者赛 VG VS Spirit第二局
2016/02/26 DOTA
[01:01:52]DOTA2-DPC中国联赛正赛 iG vs LBZS BO3 第一场 3月4日
2021/03/11 DOTA
打开电脑上的QQ的python代码
2013/02/10 Python
详细解析Python中__init__()方法的高级应用
2015/05/11 Python
python批量制作雷达图的实现方法
2016/07/26 Python
python判断数字是否是超级素数幂
2018/09/27 Python
Python调用adb命令实现对多台设备同时进行reboot的方法
2018/10/15 Python
Python使用combinations实现排列组合的方法
2018/11/13 Python
Django 路由控制的实现
2019/07/17 Python
Keras框架中的epoch、bacth、batch size、iteration使用介绍
2020/06/10 Python
canvas之万花筒效果的简单实现(推荐)
2016/08/16 HTML / CSS
养殖项目策划书范文
2014/01/13 职场文书
玩手机检讨书1000字
2014/10/20 职场文书
公司2014年度工作总结
2014/12/10 职场文书
2015年乡镇卫生院工作总结
2015/04/22 职场文书
2015年小学师德师风建设工作总结
2015/10/23 职场文书
Redis5之后版本的高可用集群搭建的实现
2021/04/27 Redis
详解SpringBoot异常处理流程及原理
2021/06/21 Java/Android
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
2022/02/12 MySQL