mysql event事件深入研究

由于最近分区表需要能够自动增加分区,所以需要用到事件event,和存储过程;遇到了一些不可思议的问题,记录下过程;

事件

事件是MySQL 5.1引入的一种新的存储代码的方式。它类似于linux的定时任务,不过是完全在MySQL内部实现的。你可以创建事件,指定MySQL在某个时候执行某段SQL代码,或者每隔一段时间执行一段MySQL代码。通常,我们会吧复杂的SQL都封装在一个存储过程中,这样事件在执行的 时候只需要做一个 简单的call调用。

事件在一个独立的事件调度线程中初始化,这个线程和处理线程连接的线程没有任何关系。他不接受任何参数,也没有任何返回值。可在MySQL日志中看到命令的执行日志,还可以在表INFORMATION_SCHEMA.EVENTS中看到各个事件的状态例如每个事件的最后执行时间(last_executed)等。

上面日志可以看到事件执行失败;原因是列和值不匹配。

上面可以查出事件的相关状态;可以看到事件的创建时间是4月4日18:41而执行时间是4月4日10:42,这个好像是没有执行,实际上已经执行成功了,好像是时区导致的时间不一致,并不会对事件执行造成任何影响(我测试是这样);

类似的,一些适用于存储过程的考虑也同样使用于事件,首先,创建事件意味着给服务器带来额外的工作。事件实现本身的开销并不大,但是事件需要执行SQL,则可能会对性能产生很大的影响。更进一步,事件和其他存储程序一样,在和基于语句复制一起工作时,也可能触发同样的问题。事件的一些典型的应用包括定期的维护任务,重建缓存,构建汇总表来模拟物化视图,或者存储于监控和诊断的状态值。

下面的例子创建了一个事件,他会每月一次针对某个数据库运行一个存储过程;

CREATE 
EVENT `NewEvent`
ON SCHEDULE EVERY 1 MONTH STARTS '2018-04-04 18:42:00'
ON COMPLETION PRESERVE
ENABLE
DO
        CALL proc_add_partition();

可以指定事件本身是否被复制。根据需要,有时候需要被复制,有时候则不需要。有时候可能希望在所有的备库上都运行某个SQL语句,不过,如果在所有的备库上都运行,可能会影响服务器性能(会对表进行枷锁);

如果一个定时事件执行需要很长的时间,则可能影响服务器性能,前面一个事件还没有执行完成,下一个事件就已经开始了。MYSQL本身不会防止这种并发,所以需要我们自己编写这种情况下的防并发代码。可以使用GET_LOCK()函数来确保当前总是只有一个事件被运行。

 
 
CREATE 
EVENT `NewEvent`
ON SCHEDULE EVERY 1 MONTH STARTS '2018-04-04 18:42:00'
ON COMPLETION PRESERVE
ENABLE
DO
BEGIN
       declare continue hanlder for SQLEXCEPLTION
        BEGIN END;
        IF GET_LOCK('table', 0) THEN 
        CALL proc_add_partition();
        END IF;
        DO RELEASE_LOCK('table');
END

    这里的CONTINUE HANLDER 用来确保,即使当事件执行出现了异样,仍然会释放所有的锁。 
 

虽然事件的执行跟连接无关,但是他仍然是线程级别的。MySQL中有一个事件调度线程,必须在配置文件中配置,或者用命令set global event_scheduler :=1;改选项一旦设置,该线程就会执行各个用户指定事件中的各段SQL代码。可以通过MySQL的错误日志了解情况。

虽然事件调度是一个单独的线程,但是事件本身是可以并发 执行的。MySQL会创建一个新的进程用于事件的执行。在事件的代码中,如果你调用函数connection_id(),也会返回一个唯一的值,和一般的线程返回的一样,虽然事件和MySQL的连接线程无关(这里的connection_id()返回的只是线程ID).这里的进程和线程生命周期就是事件的 执行事件的 执行过程。可以通过show peocesslist;查看command 总是connect。

虽然事件处理进程需要 创建一个线程来真正执行事件,但该线程在时间执行结束后会被销毁,而不会放在 缓存中 ,并且threads_created也不会增加。

猜你喜欢

转载自blog.csdn.net/qwerdf10010/article/details/79822665