Как использовать LOCK IN SHARE MODE с режимом гибернации / весны? - PullRequest
1 голос
/ 05 января 2011

Я сталкиваюсь с тупиковым сценарием при использовании MySQL и Hibernate (с Spring).Я получаю следующее сообщение об исключении:

не удалось получить или обновить следующее значение;SQL [NULL];вложенным исключением является org.hibernate.exception.LockAcquisitionException ... Обнаружена тупиковая ситуация при попытке получить блокировку;попробуйте перезапустить транзакцию

Мой MySQL db имеет уровень изоляции транзакции, настроенный для READ COMMITTED, и я проверил состояние INNODB, чтобы увидеть, что происходило при возникновении взаимоблокировки.По сути, я вижу две транзакции, в которых одна пытается выбрать строку из таблицы, а другая пытается обновить эту строку.Стол в споре здесь моя таблица "уникальный идентификатор".У меня есть общий корневой объект, который расширяют другие объекты @Entity.Этот корневой объект определяет свойство "id" и помечается @Id, @TableGenerator и @ GeneratedValue.

Некоторые размышления заставили меня поверить, что установка для LockMode значения UPGRADE для "select" в этой таблице можетпомогите и / или измените "select", чтобы вместо него использовать "select .... для обновления ", он использовал бы "select .... lock in share mode ".

Любые идеи, если установка Lockmode.upgrade действительно поможет или изменение "для обновления" на "блокировка в режиме совместного использования"?Во-вторых, как бы я сделал это с помощью Spring + Hibernate ... Я склонялся к реализации пользовательского LoadEventListener (который будет расширять DefaultLoadEventListener).

1 Ответ

0 голосов
/ 06 января 2011

Конкретный случай, с которым я столкнулся, заключался в том, что в моей таблице «генератора идентификаторов» возникали тупики. В конечном итоге я обнаружил, что мое приложение использует org.hibernate.id.MultipleHiLoPerTableGenerator, который создает оператор выбора (внутренне этот класс сохраняет его в свойстве «query») и добавляет строку «for update» (которую он фактически получает из класс org.hibernate.dialect.Dialect (метод getForUpdateString).

Решение для этого конкретного экземпляра состояло в том, чтобы генератор Id использовал «блокировку в режиме общего доступа» вместо «для обновления» при выполнении «выбора» из моей таблицы Id. Использование собственного диалекта (т. Е. Переопределение метода getForUpdateString было нежизнеспособным, т.к. я не хотел постоянно блокировать режим общего доступа, только в этом случае).

Поэтому мне пришлось создать свой собственный класс генератора Id. Мне бы очень хотелось, чтобы MultipleHiLoPerTableGenerator было немного проще в расширении (т. Е. Если бы я мог просто переопределить метод 'createSelectSql').

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