Розширення відповіді Марка ...
Коли трапляється подія очікування клієнта (наприклад, .net CommandTimeout), клієнт відправляє "ABORT" на SQL Server. Потім SQL Server просто відмовляється від обробки запитів. Жодна транзакція не відкочується, блокування не видаляється.
Тепер з'єднання повертається в пул з'єднань, тому він не закритий на SQL Server. Якщо це коли-небудь трапиться (через KILL або перезавантаження клієнта тощо), транзакції + блокування будуть очищені. Зауважте, що з'єднання sp_reset_connection не очищає їх, навіть якщо це рекламується для цього
Цей детрит від аборту заблокує інші процеси.
Спосіб зробити чіткі транзакції SQL Server + блокування на час очікування клієнта (строго, події ABORT) - це використовувати SET XACT_ABORT ON.
Ви можете перевірити це, відкриваючи 2 вікна запитів у SSMS:
Вікно 1:
У меню Запит .. Параметри запитів встановіть час очікування в 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: