使用可序列化事务后,Quartz调度程序自身死锁

时间:2016-02-26 12:43:20

标签: mysql transactions quartz-scheduler guice mybatis

我有一个带有MySQL InnoDB表的系统,一个集群的Quartz调度程序和用于db层的MyBatis。

Quartz每隔30秒运行一次作业,检查数据库中的一些内容。直到最近,当我不得不为服务方法添加org.mybatis.guice.transactional.Transactional(isolation = Isolation.SERIALIZABLE,executorType = ExecutorType.BATCH)注释时,一切都运行正常,实际上甚至没有触及数据显然失败的触发器的工作会触及。

所以,现在发生的事情是,在使用该事务化服务方法一段时间后,它可能已经失败了对自己的并发调用(虽然在日志中没有任何关于这个),每30秒我得到一个在Quartz作业中出现死锁的日志中的异常,MySQL告诉我死锁是如下:

  

最新检测到的死锁

     

160226 12:20:00    *(1)TRANSACTION:TRANSACTION 28465C8,ACTIVE 0 sec启动索引读取mysql表中使用1,锁定1 LOCK WAIT 3锁定struct(s),堆   大小376,2行锁(s)MySQL线程ID 229934,OS线程句柄   0x7efcefcf7700,查询号76969784 server-node2 192.168.0.8   system-username排序结果SELECT TRIGGER_NAME,TRIGGER_GROUP,   NEXT_FIRE_TIME,优先级来自QRTZ_TRIGGERS,其中SCHED_NAME =   ' CloudScheduler'和TRIGGER_STATE ='等待' AND NEXT_FIRE_TIME< =   1456482030017 AND(MISFIRE_INSTR = -1 OR(MISFIRE_INSTR!= -1 AND   NEXT_FIRE_TIME> = 1456481940018))按NEXT_FIRE_TIME ASC排序,   优先权DESC   * (1)等待此锁定被授予:RECORD LOCKS空格id 0页面737 n位128索引PRIMARY表   cloudsystemQRTZ_TRIGGERS trx id 28465C8锁定模式S锁定rec但是   没有间隙等待记录锁,堆没有55物理记录:n_fields 18;   紧凑格式; info bits 0 0:len 19;十六进制   5468657265436c6f75645363686564756c6572; asc CloudScheduler ;; 1:len   29; hex 41646d696e5573657253657474696e7355706461746554726967676572;   asc UserSettingsUpdateTrigger ;; 2:len 7; hex 44454641554c54; ASC   默认;; 3:len 6; hex 0000028465c2; asc e ;; 4:len 7;十六进制   20000004ca2763; asc' c ;; 5:len 23;十六进制   41646d696e5573657253657474696e6773557064617465; ASC   UserSettingsUpdate ;; 6:len 17;十六进制   41646d696e5573657253657474696e6773; asc UserSettings ;; 7:SQL NULL;   8:len 8; hex 800001531d1811b0; asc S ;; 9:len 8;十六进制   800001531d179c80; asc S ;; 10:len 4; hex 80000005; asc ;;   11:len 8; hex 4143515549524544; asc获取;; 12:len 4;十六进制   43524f4e; asc CRON ;; 13:len 8; hex 80000153195c6d28; asc S \ m(;;   14:len 8;十六进制8000000000000000; asc ;; 15:SQL NULL; 16:   len 2; hex 8000; asc ;; 17:len 0;十六进制asc ;;

     

*(2)TRANSACTION:TRANSACTION 28465C2,ACTIVE 0秒更新或删除正在使用的mysql表1,锁定1 10个锁定结构,堆大小   1248,15行锁,撤消日志条目1 MySQL线程ID 230109,OS   线程句柄0x7efcef9e7700,查询ID 76969780 server-node1   192.168.0.7 system-username更新UPDATE QRTZ_TRIGGERS设置TRIGGER_STATE ='已获取' SCHED_NAME =' CloudScheduler'和   TRIGGER_NAME =' UserSettingsUpdateTrigger'和TRIGGER_GROUP =   ' DEFAULT'和TRIGGER_STATE ='等待'   * (2)HOLDS THE LOCK(S):RECORD LOCKS space id 0 page no 737 n bits 120 table PRIMARY的{​​{1}}索引。cloudsystem trx id   28465C2 lock_mode X锁定rec而不是gap记录锁定,堆没有55   物理记录:n_fields 18;紧凑格式; info bits 0 0:len 19;   hex 5468657265436c6f75645363686564756c6572; asc CloudScheduler ;; 1:   len 29;十六进制   41646d696e5573657253657474696e7355706461746554726967676572; ASC   UserSettingsUpdateTrigger ;; 2:len 7; hex 44454641554c54; ASC   默认;; 3:len 6; hex 0000028465c2; asc e ;; 4:len 7;十六进制   20000004ca2763; asc' c ;; 5:len 23;十六进制   41646d696e5573657253657474696e6773557064617465; ASC   UserSettingsUpdate ;; 6:len 17;十六进制   41646d696e5573657253657474696e6773; asc UserSettings ;; 7:SQL NULL;   8:len 8; hex 800001531d1811b0; asc S ;; 9:len 8;十六进制   800001531d179c80; asc S ;; 10:len 4; hex 80000005; asc ;;   11:len 8; hex 4143515549524544; asc获取;; 12:len 4;十六进制   43524f4e; asc CRON ;; 13:len 8; hex 80000153195c6d28; asc S \ m(;;   14:len 8;十六进制8000000000000000; asc ;; 15:SQL NULL; 16:   len 2; hex 8000; asc ;; 17:len 0;十六进制asc ;;

     

***(2)等待此锁定被授予:记录锁空间id 0页没有759 n位120索引QRTZ_TRIGGERS的表   IDX_QRTZ_T_NFT_STcloudsystem trx id 28465C2 lock_mode X锁定rec但是   没有间隙等待记录锁,堆没有51物理记录:n_fields 5;   紧凑格式; info bits 0 0:len 19;十六进制   5468657265436c6f75645363686564756c6572; asc CloudScheduler ;; 1:len   7; hex 57414954494e47; asc WAITING ;; 2:len 8; hex 800001531d1811b0;   asc S ;; 3:len 29;十六进制   41646d696e5573657253657474696e7355706461746554726967676572; ASC   UserSettingsUpdateTrigger ;; 4:len 7; hex 44454641554c54; ASC   DEFAULT ;;

     

***我们回滚交易(1)

所以这让我很奇怪。可序列化事务的实例可能在其他地方"失败了,但这不应该导致这种现象,这种现象每次都会反复发生。也不应该同时运行多个调度程序作业。

另一个问题是@Transactional注释似乎没有回滚事务 - 在这些死锁开始出现后,数据库中的数据已损坏。有趣的是,在交易不可序列化的应用程序的其他地方,异常的回滚可以正常工作。

MyBatis文档对这些问题并不十分冗长,但我还需要做些什么才能使我的交易安全地序列化

QRTZ_TRIGGERS

1 个答案:

答案 0 :(得分:0)

这不是一个明确的答案,但同时也有太多的信息无法发表评论。

我想分享一些我的想法。

  1. 您是否100%肯定下面的肯定?正如您可能已经知道的那样,如果您的服务和Quartz作业在任何时候都使用相同的表,我会期待这种问题。
  2.   

    "实际上甚至没有触及的服务方法的注释   显然失败的触发器工作将触及的数据。"

    1. 听起来你的Quartz作业和你的交易正在发生碰撞。因此,您可能需要实现某种同步策略。例如,您可以添加事务管理器,或者可以在代码中添加某种同步块以避免此问题。
    2. 干杯,