2012-01-10 2 views
0

В приложении asp.net 2.0, которое я поддерживаю, мы столкнулись с проблемами с прерываниями транзакции (тайм-аут). Сбой кода, похоже, вызывает тайм-аут, тогда функция ведения журнала страницы, использующая транзакцию (конструктор по умолчанию), терпит неудачу (но не всегда). Тайм-аут установлен на 2 минуты.Исключение тайм-аутов транзакций и пулов соединений

Некоторые пример кода, который подобен тому, что мы имеем в нашем приложении ниже:

Try 

     Dim scope As TransactionScope = New TransactionScope(TransactionScopeOption.Required, New TimeSpan(0, 0, CInt(TransactionTimeout))) 

    **A method call that fails is here** 

    Using scope 

**other code is here** 


scope.complete 

end using 


catch 

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

Мой большой вопрос заключается в том, как объединение пулов в этом играет? Если пользователь A обращается к плохому коду, может ли это повлиять на пользователя B? Это поведение, которое мы видели. Если нет, что еще может вызвать это? Я был в MSDN, но я не могу найти ничего, что действительно щелкает со мной относительно того, что происходит и почему.

Вот соответствующая часть строки соединения:

Enlist=true;Pooling=true;Connection Lifetime=20;Max Pool Size=25;Min Pool Size=5 

FYI. Не уверен, что это актуально, но приложение использует базу данных Oracle 11g с шаблоном фабрики базы данных EntLib.

Спасибо за помощь.

ответ

1

Во-первых, если вы можете, я хотел бы изменить код, чтобы быть:

Using scope As New TransactionScope(TransactionScopeOption.Required, New TimeSpan(0, 0, CInt(TransactionTimeout))) 

Если это не представляется возможным, то вы должны обернуть свой код в Try /, наконец, заявление и распоряжаться сферы в конце концов если он установлен.

Dim scope As TransactionScope 
    Try 
     scope = New TransactionScope(TransactionScopeOption.Required, New TimeSpan(0, 0, CInt(TransactionTimeout))) 

     ' **A method call that fails is here** 

     ' **other code is here** 
     scope.complete() 
    Finally 
     If scope IsNot Nothing Then 
      Try 
       scope.Dispose() 
      Catch 
      End Try 
     End If 
    End Try 

Однако объединение пулов может играть роль в ваших проблемах с таймаутом.

Вообще говоря, соединения объединяются с помощью строки соединения, так что последующий запрос на идентичную строку соединения приведет к свободному соединению из пула с той же строкой соединения (если таковая имеется), которая будет передана запросу.

Когда соединение будет возвращено пулу, оно останется в пуле на количество секунд, указанное в вашем параметре Connection Lifetime, а затем будет освобождено, если оно не будет повторно использовано.

Исходя из этого, если у вас есть определенная информация о пользователе в строке подключения или других данных, которая зависит от подключения к соединению, если у вас более 25 пользователей выполняют операцию в 20 секундном промежутке времени, вы будете заканчиваются доступные подключения.

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

+0

Спасибо за предложения по изменению кода. Мы абсолютно внесем некоторые изменения.Можете ли вы подтвердить, что мое понимание общей проблемы имеет смысл - экземпляр TransactionScope создается, возникает ошибка и предотвращает выполнение строки scope.complete, поэтому время соединения заканчивается. Причинение последующих объектов transactionScope, которые завершают эту транзакцию, немедленно прекратить использование причины таймаута. Если это правильно, что происходит с соединением? Остается ли он в пуле? Это может привести к тому, что другой пользователь получит ту же ошибку, не попав в проблемный код? –

+0

Ваше понимание верное. Я считаю, что происходит, так как соединения никогда не закрываются/не завершаются, они никогда не возвращаются в пул соединений, который в итоге заполняется. Когда в пуле нет доступных подключений, пользователи начинают получать тайм-ауты. –

+0

Спасибо. Я не смог найти ничего, что бы точно объясняло, что происходит в этом сценарии. –