Неявная транзакция System.Transaction мешает другим моим соединениям

Я пытаюсь использовать System.Transaction.TransactionScope для создания транзакции для вызова нескольких хранимых процедур, но, похоже, она не очищается после себя. Как только транзакция завершена (зафиксирована или нет и объект области транзакции удален), последующие соединения с базой данных открываются с уровнем фиксации чтения сериализуемого, а не фиксацией чтения, как обычно.

Я открываю и закрываю соединение для каждого вызова (хорошо закрываю и возвращаюсь в пул соединений, как обычно в .NET), мне не хватает способа явно сбросить соединение, когда я закончу использовать его для транзакции? Я думал, что идея System.Transaction.TransactionScope заключалась в том, чтобы скрыть всю сложность.

Итак, мой код выглядит так:

            using (var scope = new TransactionScope())
            {
                ... make my 3 stored procedure calls ...

                scope.Complete();

                return returnCode;
            }

что я думаю, это нормальный способ сделать это. Но затем, если я посмотрю в профилировщик sqlserver, я вижу, что соединения открываются с помощью

set transaction isolation level serializable

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

Я также пробовал явно создать объект Commitabletransaction, создав явные новые транзакции вместо использования внешней, и все равно не повезло.

Мы будем очень благодарны за любые идеи о том, как это исправить, поскольку любые вызовы, использующие сериализуемое соединение, вызовут ошибку, если они попытаются использовать подсказку блокировки readpast.


person mjallday    schedule 04.12.2008    source источник


Ответы (3)


Используйте TransactionOptions.IsolationLevel

По по умолчанию он сериализуемый

TransactionOptions transactionoptions1 = new TransactionOptions();
transactionoptions1.IsolationLevel = IsolationLevel.ReadCommitted;
using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionoptions1))
{
    ... make my 3 stored procedure calls ...

    scope.Complete();

    return returnCode;
}
person gbn    schedule 04.12.2008
comment
Это текущее решение, которое я использовал для решения проблемы. Но меня интересует, почему я наблюдаю такое поведение. Конечно, последующие вызовы db не должны использовать уровень изоляции транзакции независимо от этого? - person mjallday; 05.12.2008

Вы также должны увидеть сброс (sp_reset_connection) между использованием одного и того же соединения в пуле; это не сбросит уровень изоляции? Вы пытались воспроизвести сериализуемую проблему (например, взаимоблокировки эскалации блокировки)?

person Marc Gravell    schedule 04.12.2008
comment
Я точно вижу соединение sp_reset. Я могу пройти и увидеть, как каждое соединение явно закрывается. Что вы имеете в виду, воспроизводя проблему с сериализуемыми объектами? Я единственный использую систему, когда пробую это, и у меня нет взаимоблокировок (проверка трассировки профилировщика и ведение журнала транзакций) - person mjallday; 04.12.2008
comment
Я имею в виду: вы утверждаете, что это мешает последующей деятельности базы данных, не связанной с транзакциями; Я говорю: ты уверен? Я подозреваю, что sp_reset_connection означает, что этот уровень изоляции не влияет на последующую активность db. - person Marc Gravell; 05.12.2008
comment
Чтобы убедиться наверняка, вам нужно будет проверить, не сняты ли дополнительные блокировки. Один из вариантов - сценарий эскалации блокировки, то есть spid A читает строку (без UPDLOCK), spid B читает строку, A пытается обновить строку, B пытается обновить строку. Если это заходит в тупик, spid-пакеты можно сериализовать. - person Marc Gravell; 05.12.2008
comment
Если я посмотрю на трассировку профилировщика sql, она будет выглядеть так: (spid, command) 65 exec sp_reset_connection 65 установить сериализуемый уровень изоляции транзакции 65 exec spc_payment_ledger_get @ payment_ledger_id = 33, @ member_id = 3 в этот момент транзакция фиксируется. - person mjallday; 05.12.2008
comment
сейчас просматриваю страницу на сайте. он по-прежнему использует тот же идентификатор spid и уровень изоляции даже после завершения транзакции. возможно, транзакция не завершается, но она определенно вызывает фиксацию, если только не возникает исключение, и в этом случае он должен автоматически откатиться правильно? - person mjallday; 05.12.2008
comment
Если набор установлен после сброса, тогда он действительно будет сериализуемым - находится ли spc_payment_lerger_get вне TransactionScope? Любопытный. Однако повторное использование spid ожидается с пулами соединений. - person Marc Gravell; 05.12.2008
comment
Это определенно выходит за рамки транзакции. То, что я разместил в вопросе, - это единственная транзакция в системе. Но все остальное, что вызывается впоследствии, завершится ошибкой, если будет иметь конфликтную блокирующую подсказку. любой вызов db вообще, из разных сеансов и т. д. - person mjallday; 05.12.2008

Это известное дизайнерское решение в SQL Server.

Кроме того, используя новый TransactionScope () считается вредоносным (06/2010; избегайте конструктора по умолчанию)

person user423430    schedule 20.07.2012