2016-02-26 1 views
0

У меня есть система с таблицами MySQL InnoDB, кластерный планировщик Quartz и MyBatis для слоя db.Quartz scheduler deadlocking с собой после использования сериализуемой транзакции

Quartz запускает работу каждые 30 секунд, проверяя некоторые вещи в db. Все отлично работало до недавнего времени, когда мне пришлось добавить аннотацию org.mybatis.guice.transactional.Transactional (isol = Isolation.SERIALIZABLE, executorType = ExecutorType.BATCH) для метода службы, которая на самом деле даже не касается данных, которые по-видимому, не срабатывало срабатывание триггера.

Итак, теперь случается, что после использования этого транзакционированного метода обслуживания на некоторое время, после чего он, вероятно, потерпел неудачу против одновременного вызова самого себя (в журналах ничего нет), каждые 30 секунд я получаю исключение в журналах для тупиковой ситуации в рабочих Quartz и MySQL говорит мне тупиковое было следующее:

Последним ОБНАРУЖЕН тУПИК

160226 12:20:00 * (1) СДЕЛКИ: TRANSACTION 28465C8, ACTIVE 0 сек. Начальный индекс читать таблицы mysql в использовании 1, заблокировано 1 LOCK WAIT 3 lock st ruct (s), куча размер 376, замок 2 ряд (s) MySQL идентификатор потока 229934, OS нить ручка 0x7efcefcf7700, идентификатор запроса 76969784 сервера node2 192.168.0.8 системы имя пользователя Сортировка результата ВЫБРАТЬ TRIGGER_NAME, TRIGGER_GROUP, NEXT_FIRE_TIME, ПРИОРИТЕТ ОТ QRTZ_TRIGGERS ГДЕ SCHED_NAME = 'CloudScheduler' И TRIGGER_STATE = 'ОЖИДАНИЕ' И NEXT_FIRE_TIME < = 1456482030017 И (MISFIRE_INSTR = -1 ИЛИ (MISFIRE_INSTR! = -1 и NEXT_FIRE_TIME> = 1456481940018)) ORDER BY NEXT_FIRE_TIME ASC, ПРИОРИТЕТ DESC * (1) ОЖИДАЕМ, ЧТОБЫ ДАННОЕ БЛОКИРОВАНИЕ ПРЕДУПРЕЖДЕНИЕ: ЗАПИСЬ ЗАМКИ пробел id 0 страница нет 737 n бит 128 индекс PRIMARY таблицы cloudsystem. QRTZ_TRIGGERS trx id 28465C8 блокировка режим S блокировка rec но нет промежуток ожидание запись блокировка, куча нет 55 PHYSICAL RECORD: n_fields 18; компактный формат; информационные биты 0 0: len 19; hex 5468657265436c6f75645363686564756c6572; asc CloudScheduler ;; 1: len 29; hex 41646d696e5573657253657474696e7355706461746554726967676572; asc UserSettingsUpdateTrigger ;; 2: len 7; hex 44454641554c54; asc DEFAULT ;; 3: len 6; hex 0000028465c2; asc e ;; 4: len 7; hex 20000004ca2763; asc 'c ;; 5: len 23; hex 41646d696e5573657253657474696e6773557064617465; asc UserSettingsUpdate ;; 6: len 17; hex 41646d696e5573657253657474696e6773; asc UserSettings ;; 7: SQL NULL; 8: len 8; hex 800001531d1811b0; asc S ;; 9: len 8; hex 800001531d179c80; asc S ;; 10: len 4; hex 80000005; asc ;; 11: len 8; hex 4143515549524544; asc Приобретен ;; 12: len 4; hex 43524f4e; asc CRON ;; 13: len 8; hex 80000153195c6d28; по возрастанию S \ M (;; 14: Len 8; гекс 8000000000000000; ASC ;; 15: SQL NULL; 16: Len 2; гекс 8000; по возрастанию ;; 17: Len 0; гекс; по возрастанию ;;

* (2) СДЕЛКА: ОПЕРАЦИЯ 28465C2, АКТИВНО 0 секунд обновление или удаление таблиц mysql в использовании 1, заблокировано 1 10 блокировки struct (s), размер кучи 1248, 15 строк блокировки, отменить записи журнала 1 MySQL thread id 230109, OS ручка потока 0x7efcef9e7700, идентификатор запроса 76969780 server-node1 192.168.0.7 системного имени пользователя Обновление ОБНОВЛЕНИЕ QRTZ_TRIGGERS SET TRIGGER_STATE = 'Приобретаемая', где SCHED_NAME = 'CloudScheduler' И имя_триггера = 'UserSettingsUpdateTrigger' И TRIGGER_GROUP = 'по умолчанию' И TRIGGER_STATE = 'ОЖИДАНИЕ' * (2) удерживает блокировку (S): RECORD LOCKS пробел id 0 страница нет 737 n бит 120 индекс PRIMARY таблицы cloudsystem. QRTZ_TRIGGERS trx id 28465C2 lock_mode X замки, но не зазор Замок записи, куча нет 55 ФИЗИЧЕСКАЯ ЗАПИСЬ: n_fields 18; компактный формат; информационные биты 0 0: len 19; hex 5468657265436c6f75645363686564756c6572; asc CloudScheduler ;; 1: len 29; hex 41646d696e5573657253657474696e7355706461746554726967676572; asc UserSettingsUpdateTrigger ;; 2: len 7; hex 44454641554c54; asc DEFAULT ;; 3: len 6; hex 0000028465c2; asc e ;; 4: len 7; hex 20000004ca2763; asc 'c ;; 5: len 23; hex 41646d696e5573657253657474696e6773557064617465; asc UserSettingsUpdate ;; 6: len 17; hex 41646d696e5573657253657474696e6773; asc UserSettings ;; 7: SQL NULL; 8: len 8; hex 800001531d1811b0; asc S ;; 9: len 8; hex 800001531d179c80; asc S ;; 10: len 4; hex 80000005; asc ;; 11: len 8; hex 4143515549524544; asc Приобретен ;; 12: len 4; hex 43524f4e; asc CRON ;; 13: len 8; hex 80000153195c6d28; по возрастанию S \ M (;; 14: Len 8; гекс 8000000000000000; ASC ;; 15: SQL NULL; 16: Len 2; гекс 8000; по возрастанию ;; 17: Len 0; гекс; по возрастанию ;;

*** (2) жДЕТ ЭТОТ зАМОК дЛЯ ПРЕДОСТАВЛЕНИЯ: блокировки пространства ID 0 страницы нет 759 п бит 120 указательных IDX_QRTZ_T_NFT_ST таблицы cloudsystemQRTZ_TRIGGERS TRX ID 28465C2 lock_mode X замков прна но не пробел в ожидании блокировки записи, куча нет. 51 Физическая запись: n_fields 5; компактного формата; Информация биты 0 0: Len 19; шестигранные 5468657265436c6f75645363686564756c6572; по возрастанию CloudScheduler ;; 1: Len 7; гекс 57414954494e47; по возрастанию ОЖИДАНИЯ ;; 2: Len 8; гекс 800001531d1811b0; по возрастанию S ;; 3: 1 ru 29; hex 41646d696e5573657253657474696e7355706461746554726967676572; asc UserSettingsUpdateTrigger ;; 4: len 7; hex 44454641554c54; asc DEFAULT ;;

*** МЫ ВСПЯТЬ TRANSACTION (1)

Так что это заставляет меня задаться вопросом. Возможно, что экземпляр сериализуемой транзакции «в другом месте» потерпел неудачу, но это не должно вызывать этого явления, которое происходит неоднократно и каждый раз. Также не должно быть одновременно заданий нескольких планировщиков.

Другая проблема заключается в том, что аннотация @Transactional, похоже, не откатывает транзакцию - в базе данных появляются поврежденные данные после появления этих взаимоблокировок. Интересно, что в другом месте приложения, где транзакции не сериализуемы, откаты на исключениях работают корректно.

В MyBatis документация не очень многословен об этих вопросах, но есть что-то еще мне нужно делать, чтобы сделать свои операции безопасно сериализуемым чем

@Transactional(isolation=Isolation.SERIALIZABLE, executorType=ExecutorType.BATCH) 
public void doCoolStuff(...) { 

} 
+0

Пересмотрите ваш уровень изоляции; сериализации! Вы также должны убедиться, что существует только один экземпляр этих служб, то есть время выполнения службы не должно перекрываться. – cdaiga

+0

Не вариант. Транзакции должны быть сериализуемыми, потому что они должны выполняться так: если они произошли один за другим, и, очевидно, транзакционная ситуация существует именно потому, что вызовы службы могут и будут перекрываться. – CptPicard

ответ

0

Это не окончательный ответ, но в то же время слишком много информации, чтобы добавить комментарий.

Я хотел бы поделиться некоторыми из своих мыслей.

  1. Вы действительно являетесь ли вы в этом уверены? Как вы уже знаете, я бы ожидал такой проблемы, если ваша служба и ваши задания Quartz используют одни и те же таблицы в любой момент.

«аннотаций для метода обслуживания, что на самом деле даже не трогать данные , что работа, по-видимому неудовлетворительную триггера будет трогать.»

  1. Мне кажется, что ваши задания на кварце и ваши транзакции сталкиваются. Поэтому вам может потребоваться реализация какой-либо стратегии синхронизации. Например, вы можете добавить менеджера транзакций, или вы могли бы добавить какие-то синхронизированные блоки в свой код, чтобы избежать этой проблемы.

Cheers,

+0

Я впоследствии пошел и решил это с блокировкой, но я, конечно, все еще интересуюсь, почему это произошло ... да, я вполне уверен, что данные не касаются. Однако я предполагаю, что сериализуемые транзакции могут иметь довольно широкое представление о том, что касается ... и MySQL не слишком хорош в таких вещах или, по крайней мере, это мое впечатление. Я не совсем уверен, какой дополнительный менеджер транзакций потребуется в этой настройке Guice + Mybatis - конечно, это база данных, а не некоторые явные синхронизированные блоки в коде Java, которые должны обрабатывать эти вещи! – CptPicard