Базовая проблема, которую я хочу решить, выполняет задачу, которая генерирует несколько временных таблиц в MySQL, который должен остаться вокруг достаточно долго для выборки результатов Java после того, как они создаются. Из-за размера включенных данных задача должна быть выполнена в пакетах. Каждый пакет является вызовом к хранимой процедуре, названной через JDBC. Весь процесс может занять полчаса или больше для большого набора данных.
Для обеспечения доступа к временным таблицам я выполняю всю задачу, начинаю заканчивать в единственной транзакции Spring с TransactionCallbackWithoutResult. Иначе я мог получить другое соединение, которое не имеет доступа к временным таблицам (это иногда происходило бы, прежде чем я перенес все в транзакцию).
Это хорошо работало в моей среде разработки. Однако в производстве я получил следующее исключение:
java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
Это произошло, когда другая задача пыталась получить доступ к некоторым из тех же таблиц во время выполнения моей длительной транзакции. То, что смущает меня, - то, что длительная транзакция только вставляет или обновляет во временные таблицы. Весь доступ к невременным таблицам является выборами только. Из того, что документация, которую я могу найти, уровень изоляции транзакции Spring по умолчанию, не должна заставлять MySQL блокироваться в этом случае.
Так мой первый вопрос, действительно ли это - правильный подход? Я могу удостовериться, чтобы я неоднократно получил то же соединение через шаблон Hibernate без длительной транзакции?
Если длительный подход транзакции является корректным, что я должен проверить с точки зрения уровней изоляции? Мое понимание корректно, что уровень изоляции по умолчанию в транзакциях Spring/MySQL не должен блокировать таблицы, к которым только получают доступ через выборы? Что я могу сделать для отладки, какие таблицы, вызывающие, являются конфликтом и препятствуют тому, чтобы те таблицы были заблокированы транзакцией?
Я считаю, что держать транзакцию открытой в течение длительного времени злом. За мою карьеру определение «расширенный» снизилось с секунд до миллисекунд.
Это непрекращающийся источник неповторимых проблем и головных уборов.
В этом случае я бы не остановился и вел «рабочий журнал» в программном обеспечении, который вы можете воспроизвести в обратном порядке, чтобы очистить его в случае сбоя партии.
Когда вы говорите, что ваша таблица временная, является ли она транзакционной? Это может привести к тому, что другие транзакции (возможно, в другой транзакции) не смогут увидеть/доступ к ней. Возможно, объединение реальной и временной таблиц каким-то образом блокирует реальную таблицу.
Первопричина: Пытались ли вы использовать инструменты MySQL, чтобы определить, что блокирует соединение? Это может быть что-то вроде блокировки следующей строки. Я не очень хорошо знаю инструменты MySQL, но в oracle вы можете увидеть, какие соединения блокируют другие соединения.
Таймаут транзакции: Вам следует создать второй пул соединений/источник данных с гораздо большим таймаутом. Используйте этот пул соединений для вашей долго выполняющейся задачи. Я думаю, что ваша производственная среда "пытается" помочь вам, обнаруживая застрявшие соединения.