Долгосрочные транзакции с помощью Spring и Hibernate? - PullRequest
5 голосов
/ 02 июня 2010

Основной проблемой, которую я хочу решить, является запуск задачи, которая генерирует несколько временных таблиц в MySQL, которые должны оставаться достаточно долго, чтобы получать результаты из Java после их создания. Из-за размера используемых данных, задача должна быть выполнена в пакетном режиме. Каждый пакет - это вызов хранимой процедуры, вызываемой через JDBC. Весь процесс может занять полчаса или более для большого набора данных.

Чтобы обеспечить доступ к временным таблицам, я запускаю всю задачу от начала до конца в одной транзакции Spring с TransactionCallbackWithoutResult. В противном случае я мог бы получить другое соединение, которое не имеет доступа к временным таблицам (это могло случиться до того, как я завернул все транзакции).

Это нормально работало в моей среде разработки. Однако на производстве я получил следующее исключение:

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction

Это произошло, когда другая задача пыталась получить доступ к некоторым из тех же таблиц во время выполнения моей длительной транзакции. Что меня смущает, так это то, что длительная транзакция только вставляет или обновляет временные таблицы. Весь доступ к временным таблицам только для избранных. Из документации, которую я могу найти, уровень изоляции транзакций Spring по умолчанию не должен вызывать блокировку MySQL в этом случае.

Итак, мой первый вопрос, это правильный подход? Могу ли я убедиться, что я получаю одно и то же соединение через шаблон Hibernate без длительной транзакции?

Если подход с длительной транзакцией является правильным, что я должен проверить с точки зрения уровней изоляции? Верно ли мое понимание того, что уровень изоляции по умолчанию в транзакциях Spring / MySQL не должен блокировать таблицы, доступ к которым осуществляется только с помощью выбора? Что я могу сделать, чтобы отладить, какие таблицы вызывают конфликт, и предотвратить блокировку этих таблиц транзакцией?

Ответы [ 3 ]

6 голосов
/ 02 июня 2010

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

Это бесконечный источник неповторяющихся проблем и проблем с царапинами.

Я бы прикусил пулю в этом случае и вел бы «рабочий журнал» в программном обеспечении, которое вы можете воспроизвести в обратном порядке для очистки в случае сбоя пакета.

1 голос
/ 02 июня 2010

Когда вы говорите, что ваша таблица временная, это область действия транзакции? Это может привести к тому, что другие транзакции (возможно, в другой транзакции) не смогут увидеть / получить к ней доступ. Возможно, соединение, включающее реальную таблицу и временную таблицу, каким-то образом блокирует реальную таблицу.

Основная причина: Вы пытались использовать инструменты MySQL, чтобы определить, что блокирует соединение? Это может быть что-то вроде блокировки следующей строки. Я не очень хорошо знаю инструменты MySQL, но в oracle вы можете видеть, какие соединения блокируют другие соединения.

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

0 голосов
/ 04 сентября 2012

Как упомянул Джастин относительно времени ожидания транзакции, я недавно столкнулся с проблемой, в которой пул соединений (в моем случае tomcat dbcp в Tomcat 7) имел настройку, которая должна была отмечать пометку для длительно работающих соединений, а затем закрывать их. После настройки этих параметров я мог избежать этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...