Час очікування транзакцій на 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:

У меню Запит .. Параметри запитів встановіть час очікування в 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?
kamilk

11

Я відповідаю на це не вагаючись, оскільки у вашому описі проблеми недостатньо інформації, щоб бути на 100% впевненим, що це найкраща порада. "Висить або кидає виняток" говорить про те, що джерело проблеми не є належним чином зрозумілим, тому дійте обережно.

Мабуть, найпростішим рішенням цього є SET XACT_ABORT ON.

XACT_ABORTвизначає, чи буде SQL Server відмовляти транзакцію у випадку помилки під час виконання. За замовчуванням SET XACT_ABORT OFFбуде відкликатися лише те твердження, яке спричинило помилку, а будь-яка батьківська транзакція залишається відкритою.

Побічним ефектом налаштування за замовчуванням "gotcha" є те, що тайм-аут може спричинити точно таку ж проблему, відкриту транзакцію, яка несе відповідальність клієнтів за обробку та відкат. Якщо клієнт не спробує / catch / rollback, транзакція залишатиметься відкритою до тих пір, поки не буде проведено (і я цитую @gbn) ультра-насильство KILL <spid>.

Часто цитовані статті Ерланда Соммарського про поводження з помилками в SQL Server містять усі передумови та стратегію, необхідні для роботи з цими сценаріями тощо.

Редагувати (наступний коментар): Для ідентифікації відкритих транзакцій, sp_whoisactive , мабуть, є найбільш повною функцією.


Я знайшов за допомогою Googling способів знайти відкриті транзакції, коли відбувається повішення - можливо, це найкраще рішення. Тобто знайти причину незакритої транзакції в коді та виправити отвори в коді. Для довідок для інших. 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.