2010-08-03 1 views
7

Наше приложение (использующее NHibernate и ASP.NET MVC), когда оно подвергается стресс-тестам, вызывает много ошибок транзакции NHibernate. Основные типы:Обработка ошибок транзакции NHibernate

  1. сделка не подключены или была отключена
  2. Row была обновлена ​​или удалена другой транзакция (или отображение неспасенного значения было неправильным)
  3. транзакций (Process ID 177) была заведена в тупик на блокировать ресурсы другим процессом и был выбран в качестве жертвы взаимоблокировки. Перезапустите транзакцию.

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

В. Как мы управляем сеансами и транзакциями?

A. Мы используем Autofac. Для каждого запроса сервера мы создаем новый контейнер запроса, который имеет сеанс в области жизненного цикла контейнера. При активации сеанса мы начинаем транзакцию. Когда запрос завершается, мы совершаем транзакцию. В некоторых случаях транзакция может быть огромной. Чтобы упростить, каждый запрос сервера содержится в транзакции.

+0

Как вы управляете сеансами и транзакциями? –

+0

Вы когда-нибудь находили решение? –

ответ

0

Под напряжением вы имеете в виду millions of database entries? Если это так, посмотрите на следующий пост:

+1

№ Мы провели стресс-тест в веб-приложении, используя JMeter, имитируя многочисленные пользователи, работающие на сайте одновременно – Zuber

1

взглянуть на эту тему: http://n2cms.codeplex.com/Thread/View.aspx?ThreadId=85016

В основном то, что он говорит, как возможная причина этого исключения:

2010-02-17 21: 01: 41,204 1 WARN NHibernate.Util.ADOExceptio nReporter - System.Data.SqlClient.SqlException: Журнал транзакций для базы данных 'databasename' заполнен. Для того, чтобы выяснить, почему пространство в журнале не могут быть повторно использованы, смотрите колонку log_reuse_wait_desc в sys.databases

как размер журнала транзакций является пропорционально количеству работы, проделанной в ходе сделки, возможно, вы должны обратите внимание на то, что ваши транзакционные границы обрабатываются командами обработчиков команд в записи транзакции. Затем вы, с сеансом # X, загрузите состояние, которое хотите изменить, измените его и зафиксируйте, все как одну единицу работы в #X.

Что касается чтения вещей, у вас может быть еще один ISession # Y, который считывает данные; этот ISession может использоваться для пакетного чтения в пределах, например. RepeatableRead или что-то подобное с функцией Futures и может просто считываться из кеша (albiet - это костыль). Выполнение этого способа может помочь вам оправиться от «ошибок», которых нет; оживления, тупики и операции с жертвами.

Проблема с использованием транзакции за запрос заключается в том, что ваш ISession приобретает много данных о бухгалтерском учете во время работы, все из которых являются частью транзакции.Следовательно, база данных помещает данные (rols, cols, tables и т. Д.) Как участвующие в транзакции, заставляя график ожидания охватывать «сущности» (в смысле базы данных, а не DDD-смысл), которые на самом деле не являются частью транзакционной границы команды, которую ваша заявка приняла.

Для записи (другие люди, занимающиеся поиском по Google), Фабио имел a post, занимающийся обработкой исключений из слоя данных. Цитирование некоторых из его кода;

public class MsSqlExceptionConverterExample : ISQLExceptionConverter 
{ 
    public Exception Convert(AdoExceptionContextInfo exInfo) 
    { 
     var sqle = ADOExceptionHelper.ExtractDbException(exInfo.SqlException) as SqlException; 
     if(sqle != null) 
     { 
      switch (sqle.Number) 
      { 
       case 547: 
        return new ConstraintViolationException(exInfo.Message, 
         sqle.InnerException, exInfo.Sql, null); 
       case 208: 
        return new SQLGrammarException(exInfo.Message, 
         sqle.InnerException, exInfo.Sql); 
       case 3960: 
        return new StaleObjectStateException(exInfo.EntityName, exInfo.EntityId); 
      } 
     } 
     return SQLStateConverter.HandledNonSpecificException(exInfo.SqlException, 
      exInfo.Message, exInfo.Sql); 
    } 
} 
  • 547 это число исключений для ограничения конфликта.
  • 208 - номер исключения для недопустимого имени объекта в SQL.
  • 3960 - номер исключения для транзакции изоляции моментального снимка, прерванный из-за конфликта обновлений.

Итак, если вы сталкиваетесь с проблемами параллелизма, такими как то, что вы описываете; помните, что они аннулируют ваш ISession и что вам придется обрабатывать их, как указано выше.

Часть того, что вы, возможно, ищете, - это CQRS, где у вас есть отдельные стороны чтения и записи. Это может помочь: http://abdullin.com/cqrs/, http://cqrsinfo.com.

Итак, подведем итоги; ваши проблемы могут быть связаны с тем, как обрабатывать транзакции. Также попробуйте запустить select log_wait_reuse_desc from sys.databases where name='MyDBName' и посмотреть, что он вам дает.

1

Эта нить имеет объяснение: http://groups.google.com/group/nhusers/browse_thread/thread/7f5fb68a00829d13

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

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

0

Я знаю, что это сообщение было какое-то время назад, и предположим, что вы исправили его, но похоже, что у вас есть проблемы с совместным использованием NHibernate ISession, которые не являются потокобезопасными. В основном 1 поток запускает транзакцию, а другой пытается закрыть ее, вызывая всевозможные хаосы.

 Смежные вопросы

  • Нет связанных вопросов^_^