Поддержка ORM для обработки тупиков - PullRequest
7 голосов
/ 27 февраля 2009

Знаете ли вы какой-либо инструмент ORM, который предлагает восстановление тупиков? Я знаю, что взаимоблокировки - это плохо, но иногда любая система страдает от этого при правильном количестве нагрузки. В Sql Server сообщение о взаимоблокировке гласит «Повторите транзакцию», поэтому я подозреваю, что повторный запуск оператора взаимоблокировки является желательной функцией в ORM.

Ответы [ 5 ]

4 голосов
/ 01 марта 2009

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

Если это не помогает полностью избежать взаимоблокировок, или у вас нет времени, чтобы внедрить и протестировать настоящее исправление сейчас, конечно, вы можете просто попробовать / поймать вокруг вашего сохранения / фиксации / сохранения или чего-то еще вызовите, проверьте перехваченные исключения, если они указывают, что сбойная транзакция является «жертвой тупика», а затем просто вызовите save / commit / persist после нескольких секунд ожидания. Хорошая идея - подождать несколько секунд, поскольку взаимные блокировки часто указывают на наличие временного пика транзакций, конкурирующих за одни и те же ресурсы, и повторное повторение одной и той же транзакции снова и снова, вероятно, ухудшит ситуацию.

По той же причине вы, вероятно, не захотите убедиться, что пытаетесь повторить ту же транзакцию только один раз.

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

1 голос
/ 01 марта 2009

Следует ожидать взаимных блокировок, и SQL Server, похоже, хуже в этом плане, чем другие серверы баз данных. Во-первых, вы должны попытаться минимизировать ваши тупики. Попробуйте использовать SQL Server Profiler , чтобы выяснить, почему это происходит и что вы можете с этим сделать. Затем настройте ORM, чтобы он не читал после выполнения обновления в той же транзакции, если это возможно. Наконец, после того, как вы это сделаете, если вам случится использовать Spring и Hibernate вместе, вы можете установить перехватчик, чтобы следить за этой ситуацией. Расширьте MethodInterceptor и поместите его в ваш bean-компонент Spring под interceptorNames. Когда перехватчик запущен, используйте invocation.proceed () для выполнения транзакции. Перехватывайте любые исключения и определяйте, сколько раз вы хотите повторить попытку.

0 голосов
/ 07 марта 2009

Я бросил быстрый взгляд (без сомнения, вы тоже) и не смог найти ничего, что подсказывало бы, что Hibernate по крайней мере предлагает это. Вероятно, это связано с тем, что ORM считают, что это выходит за рамки проблемы, которую они пытаются решить.

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

0 голосов
/ 04 марта 2009

o / r mapper не может обнаружить это, так как внутри СУБД всегда возникает тупик, который может быть вызван блокировками, установленными другими потоками или даже другими приложениями.

Чтобы фрагмент кода не создавал тупиковую ситуацию, всегда используйте следующие правила: - делать выборку вне транзакции. Поэтому сначала выберите, затем выполните обработку, затем выполните операторы DML, такие как вставка, удаление и обновление. - каждое действие внутри метода или серии методов, которые содержат / работают с транзакцией, должны использовать одно и то же соединение с базой данных. Это необходимо, потому что, например, блокировки записи игнорируются операторами, выполняемыми по одному и тому же соединению (поскольку это же соединение устанавливает блокировки;)).

Часто взаимоблокировки возникают из-за того, что либо код извлекает данные внутри транзакции, которая вызывает открытие НОВОГО соединения (которое должно ожидать блокировку), либо использует другие соединения для операторов в транзакции.

0 голосов
/ 03 марта 2009

Одна система, над которой я работал, была основана на «командах», которые затем передавались в базу данных, когда пользователь нажимал «Сохранить», она работала так:

While(true)
   start a database transaction
   Foreach command to process
      read data the command need into objects
      update the object by calling the command.run method
   EndForeach
   Save the objects to the database
   If not deadlock
     commit the database transaction
    we are done
   Else 
     abort the database transaction
    log deadlock and try again
   EndIf
EndWhile

Вы можете сделать что-то подобное с любым ORM; мы использовали собственную систему доступа к данным, так как ORM в то время были слишком новыми.

Мы запускаем команды вне транзакции, пока пользователь взаимодействовал с системой. Затем повторно запустите их, как указано выше (когда вы используете «сохранить»), чтобы справиться с изменениями, внесенными другими людьми. Поскольку у нас уже был хороший идеал для строк, которые должна изменить команда, мы могли бы даже использовать подсказки блокировки или «выбрать для обновления», чтобы снять все блокировки записи, которые нам были нужны в начале транзакции. (Мы сократили набор строк для обновления, чтобы еще больше уменьшить количество взаимоблокировок)

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