Тайм-аут транзакции SQL Server

9

Есть ли способ в SQL Server 2008 R2 вызвать тайм-аут для модификации базы данных, включающей транзакцию? У нас есть сценарий, в котором код нашего приложения зависает или выдает исключение и не может выполнить откат или фиксацию. Это приводит к зависанию других сеансов в ожидании завершения транзакции.

Дэвид Грей Райт
источник

Ответы:

20

Расширяя ответ Марка ...

Когда происходит событие тайм-аута клиента (например, .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:

ГБН
источник
Будущее говорит привет! «Обратите внимание, что sp_reset_connection не будет или не удаляет их, даже если об этом объявлено», - я не верю, что это больше верно в современных версиях SQL Server?
Камилк
11

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

Самое простое решение этого, вероятно SET XACT_ABORT ON.

XACT_ABORTопределяет, будет ли SQL Server выполнять откат транзакции в случае ошибки во время выполнения. По умолчанию SET XACT_ABORT OFFвыполняется откат только оператора, вызвавшего ошибку, при этом любая родительская транзакция остается открытой.

Побочным эффектом «по умолчанию» в настройке по умолчанию является то, что тайм-аут может вызвать точно такую ​​же проблему - открытую транзакцию, за выполнение которой отвечает клиент и выполняет откат. Если клиент не попытается / перехватить / откатить, транзакция останется открытой до тех пор, пока на нее не будет обращено внимание (и я цитирую @gbn) с применением насилия KILL <spid>.

В часто цитируемом Erland Sommarskog в статьи об обработке ошибок в SQL Server содержит все предпосылки и стратегию, необходимую для решения этих сценариев и многих других.

Редактировать (следующий комментарий): Чтобы идентифицировать открытые транзакции, sp_whoisactive является, вероятно, наиболее полной функцией.

Марк Стори-Смит
источник
С некоторыми поисками в Google я нашел способы найти открытые транзакции, когда происходит зависание - возможно, это лучшее решение. То есть найти причину незакрытой транзакции в коде и исправить дыры в коде. Для справки для других. DBCC OPENTRAN возвращает самую старую активную транзакцию -> msdn.microsoft.com/en-us/library/ms182792.aspx Или что-то еще подобное? -> weblogs.sqlteam.com/mladenp/archive/2008/04/29/…
Дэвид Грей Райт
Я всегда думал, что Эрланд не сделал правосудия по SET XACT_ABORT sommarskog.se/error-handling-I.html#XACT_ABORT
gbn