Расширяя ответ Марка ...
Когда происходит событие тайм-аута клиента (например, .net CommandTimeout), клиент отправляет «ABORT» на SQL Server. SQL Server просто прекращает обработку запросов. Откат транзакции не производится, блокировки не снимаются.
Теперь соединение возвращается в пул соединений, поэтому оно не закрывается на SQL Server. Если это произойдет (через KILL или перезагрузку клиента и т. Д.), Транзакции + блокировки будут очищены. Обратите внимание, что sp_reset_connection не будет или не очищает их, даже если это было объявлено
Этот детрит от аборта заблокирует другие процессы.
Чтобы сделать SQL Server четкими транзакциями + блокировки по тайм-ауту клиента (строго, события ABORT), используйте SET XACT_ABORT ON.
Вы можете проверить это, открыв 2 окна запроса в SSMS:
Окно 1:
В меню Query..Query Options установите время ожидания 5 секунд, затем запустите
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
Окно 2, это будет ждать вечно (или истечет время ожидания)
SELECT * FROM sometable
У SET XACT_ABORT ON также есть интересные побочные эффекты:
- При неявном откате @@ TRANCOUNT устанавливается равным нулю, но ошибка 266 подавляется (это происходит, если @@ TRANCOUNT отличается при входе и выходе из сохраненного процесса)
- XACT_STATE будет -1 (это «обречено»)
Комбинация этого означает, что вы не можете использовать SAVEPOINTS (хотя я не могу вспомнить точное поведение) для частичных фиксаций / откатов. Который мне подходит
ТАК ссылки на SET XACT_ABORT:
На вложенных хранимых процессах:
На sp_reset_connection:
Я отвечаю на это с нерешительностью, поскольку в вашем описании проблемы недостаточно информации, чтобы быть на 100% уверенным, что это лучший совет. «Висит или выбрасывает исключение» предполагает, что источник проблемы не совсем понятен, поэтому действуйте с осторожностью.
Самое простое решение этого, вероятно
SET XACT_ABORT ON
.XACT_ABORT
определяет, будет ли SQL Server выполнять откат транзакции в случае ошибки во время выполнения. По умолчаниюSET XACT_ABORT OFF
выполняется откат только оператора, вызвавшего ошибку, при этом любая родительская транзакция остается открытой.Побочным эффектом «по умолчанию» в настройке по умолчанию является то, что тайм-аут может вызвать точно такую же проблему - открытую транзакцию, за выполнение которой отвечает клиент и выполняет откат. Если клиент не попытается / перехватить / откатить, транзакция останется открытой до тех пор, пока на нее не будет обращено внимание (и я цитирую @gbn) с применением насилия
KILL <spid>
.В часто цитируемом Erland Sommarskog в статьи об обработке ошибок в SQL Server содержит все предпосылки и стратегию, необходимую для решения этих сценариев и многих других.
Редактировать (следующий комментарий): Чтобы идентифицировать открытые транзакции, sp_whoisactive является, вероятно, наиболее полной функцией.
источник