Сплячий SPID блокує інші транзакції


16

У мене справді виникають проблеми з відстеженням блокування, яке ми відчуваємо.

Статус кореневого блокування SPID - "сплячий", cmd - "ЗАЧЕКАЮЧА КОМАНДА", і sqltextє SET TRANSACTION ISOLATION LEVEL READ COMMITTED.

Коли я переглядаю звіт "Найпопулярніші транзакції за кількістю заблокованих транзакцій", оператор блокування SQL - "-".

Я провів трасування на SQL, і коли відбувається блокування, відстежуючи кореневе блокування SPID, але це насправді не привело мене нікуди. Останнє твердження про те саме, що і sqltextвищеSET TRANSACTION ISOLATION LEVEL READ COMMITTED .

Я перевірив всі пов'язані з цим збережені процедури, щоб переконатися, що вони мають TRY / CATCH BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN (ми використовуємо збережені процедури для всього, щоб не було запущено автономних операторів). Ця проблема почала відбуватися протягом останніх 24 годин, і ніхто не претендує на внесення змін у систему.

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

Переглядаючи всю інформацію про сліди, оператор EXEC для цієї збереженої процедури перераховувався часом, але НІКОЛИ перед тим, як БЛОК стався на блокуванні SPID. Здавалося, що, починаючи блокування, слід не записував його виконання (або будь-яке з заяв всередині нього). Однак є й інші часи, коли трасування записувало його виконання та блокування не сталося.

Збережений звіт про помилку процедури надходив від користувача, і я зміг знайти декілька операторів EXEC у слідах та запустити їх у SSMS. Ніколи, коли я запускав їх, у нас не було жодних блокувань або вони висіли. Вони пройшли так, як і очікувалося (блок вилову запустився та повернув транзакцію після помилки). Вирішивши виправлення збереженої процедури, ми знову не бачили проблеми.


Я припускаю, що ім'я хоста блокуючого SPID зовсім не допомогло?
Джон Сейгель

Ні, це лише IP-адреса одного з наших веб-серверів ... У нас є ще одна ідея змінити кожен вхід у SQL для кожного виклику SPROC під час процесу входу / реєстрації (який, на наш погляд, виникає помилка), на окреме ім'я користувача, яке може допоможіть нам виділити, який SPROC може викликати блокування.
Бред

1
TRY / CATCH не буде вловлювати помилки компіляції, а невідповідна вставка стовпця буде такою помилкою компіляції. Це також ніколи не призведе до багатьох подій XX: завершених профілів.
Рем Русану

1
Це насправді не помилка компіляції в цьому випадку, тому що геніальний розробник використовував INSERT INTO [table] SELECT * від [othertable], і він не потрапив у одноранговий. Я запускав SPROC на розробку 1000 разів від ColdFusion за 3 одночасні сесії, і це ніколи не залишало відкритої транзакції, як це було у виробництві.
Бред

Відповіді:


10

З коментарів, я здогадуюсь, у вас був час очікування команди Command, який перервав SQL-запит. Це не дає змоги повернути транзакцію, оскільки з'єднання залишається відкритим на SQL Server через об'єднання з'єднань.

Отже, вам потрібно використовувати SET XACT_ABORT ON або додати код відката клієнта

Дивіться час очікування транзакцій SQL Server для всіх деталей


Усі наші SPROC містять блоки TRY / CATCH та оператори BEGIN TRAN / COMMIT TRAN / ROLLBACK TRAN, ROLLBACK - у CATCH. Чи все-таки XACT_ABORT матиме ефект?
Бред

@Brad: так. Дивіться моє посилання. Блок лову не потрапляє на CommandTimeout
gbn

gbn: Спасибі Я все ще плутаюсь. Наші з’єднання встановлені таким чином, щоб ніколи не очікувати (0). Отже, ви говорите, якщо ми повторно використовуємо з'єднання, і з'єднання запускає SPROC з помилкою (у якій є блоки TRY / CATCH і TRAN), воно може якось ніколи не запускати ROLLBACK у блоці CATCH, таким чином блокуючи таблиці та зберігаючи транзакцію відчинено? Це не має для мене сенсу.
Бред

@Brad: SPROC з помилкою потрапить у блок CATCH. Я не сказав інакше чи інакше. Але в моєму посиланні вказано, що станеться, якщо у вас CommandTimeout, який відрізняється від ConnectionTimeout. Клієнт каже "перервати", і SQL Server припиняє обробку. Ergo, блок CATCH або відкат або фіксація ніколи не потрапляють
gbn

Я не думаю, що у нас вказано CommandTimeout. Усі наші збережені процедури проходять тестування за допомогою sqlstress і повинні виконувати менше 1000 мс у 10 користувачів 10 ітерацій (як мінімум). Я все ще дуже розгублений щодо того, що сталося, але я актуалізую питання з тим, що ми виявили, що це проблема.
Бред

9

Використовуйте most_recent_sql_handle в sys.dm_exec_connections, щоб побачити останнє виконання, яке було виконано.

SELECT  t.text,
        QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
        + QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
        c.connect_time,
        s.last_request_start_time,
        s.last_request_end_time,
        s.status
FROM    sys.dm_exec_connections c
JOIN    sys.dm_exec_sessions s
        ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE   c.session_id = 72;--your blocking spid

Також перевірте, чи є відкриті транзакції для цього павука

SELECT  st.transaction_id,
        at.name,
        at.transaction_begin_time,
        at.transaction_state,
        at.transaction_status
FROM    sys.dm_tran_session_transactions st
JOIN    sys.dm_tran_active_transactions at
        ON st.transaction_id = at.transaction_id
WHERE   st.session_id = 72;--your blocking spid

Ви також можете використати DBCC INPUTBUFFER(spid)для перегляду останнього виконаного SQL.
Майк Фаль

Я використовував усі ці, і остання команда - це завжди те, що я розмістив у своєму початковому дописі: НАСТРОЙКА РІВНЯ ІЗОЛЯЦІЇ ТРАНЗАКЦІЇ ЧИТАТИ ЗВ'ЯЗАНО. Я також запустив DBCC OPENTRAN і бачу, що існує відкрита транзакція для блокування PID.
Бред

Мій перший вибір також дає вам назву процедури, якщо заява дійсно є частиною процедури.
Себастьян Майне

Запевняю, що ми не використовуємо жодних запитів adhoc з наших веб-серверів, і коли я запускаю перший запит, навіть без пункту WHERE, я отримую лише названий SPROC на кількох сесіях SQL, решта цього стовпця - NULL.
Бред

Я помічаю, що у мене є безліч сеансів, які говорять "НАСТРОЙКА ІЗОЛЯЦІЇ ІЗОЛЯЦІЇ ТРАНЗАКЦІЇ ПРОЧИТАЙТЕ ЗАВЕРШЕНО", і всі вони з ColdFusion (основний сценарій, який використовується на наших веб-серверах). Можливо, ColdFusion, коли простою видає цей оператор, щоб він відкрив з'єднання (оскільки він налаштований тримати з'єднання відкритими).
Бред

4

Ви пробували використовувати sp_whoisactive Адама Маханіка ? Існує можливість отримати зовнішню команду, щоб побачити, чи дійсно це в межах проц. Можливо, додаток тримає відкриту транзакцію, а не здійснює її. Спробуйте також поглянути на DBCC OPENTRAN .


Дякуємо за DBCC OPENTRAN. Це мені говорить про те, що блокуючий PID має відкриту транзакцію, але більше деталей немає. sp_whoisactive повертає ту саму інформацію про заблокований процес, що і мені вдалося отримати самостійно. Досі немає деталей щодо того, що відбувається, окрім "НАЗНАЧИТИ РОЗВИТК ІЗОЛЯЦІЇ ТРАНЗАКЦІЇ, ЧИТАЙТЕ ЗАВДАННЯ"
Бред
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.