Тупик у видаленні заяви


11

Я отримую тупик, коли працює робота SQL Server. Тупик відбувається на простому операторі DELETE. Я міг би подумати, що для запуску тупикового зв'язку повинен працювати запит SELECT / UPDATE? Але схоже, що це ВІДКЛЮЧИТИ / ВИДАЛИТИ тупик ...

Що я шукаю - це те, чому я отримую DELETE / DELETE тупик. Це (наскільки мені відомо) проходить за різними параметрами.

Будь-які ідеї? Спасибі.

deadlock-list
2014-05-20 07:30:09.66 spid25s      deadlock victim=process409048
2014-05-20 07:30:09.66 spid25s       process-list
2014-05-20 07:30:09.66 spid25s        process id=process409048 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127294 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x397219620 lockMode=U schedulerid=5 kpid=3792 status=suspended spid=150 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process432e08 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=2648 ownerId=629859744 transactionname=DELETE lasttranstarted=2014-05-20T07:30:04.833 XDES=0x4c3426b50 lockMode=U schedulerid=6 kpid=5988 status=suspended spid=146 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:04.833 lastbatchcompleted=2014-05-20T07:30:04.820 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629859744 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process39ea562c8 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x13e0e4b50 lockMode=U schedulerid=2 kpid=7124 status=suspended spid=150 sbid=0 ecid=1 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2

5
Ні, тупик може статися в інших сценаріях поза SELECT / UPDATE. Все, що вам потрібно, - це два процеси, для кожного з яких потрібен ресурс, який має інший. (1) Чи є виписки DELETE частиною більшої транзакції? (2) Чи можете ви розмістити XML куди-небудь тупик кудись, замість шаленого тексту журналу помилок?
— Аарон Бертран

Чи можете ви, будь ласка, опублікувати табличну схему dbo.UserDetailsDataвключення всіх індексів? Крім того, чи знаєте ви, чи викликаються ці твердження з однаковими параметрами? З огляду на те, що для обох використовується нульовий журнал, мені цікаво, чи все, що вам потрібно зробити, це серіалізація дзвінків, оскільки вони наступають один на одного.
— Джон Сейгель

Як отримати XML? Отримала помилку з журналів помилок SQL Server. Виписки називаються з різними параметрами. Нещодавно ми додали ряд відфільтрованих індексів, які фільтрують у полі UserDate.
— K09

Ловіть подію графіка тупикового кута в Profiler. Потім, після того, як ви його вловите, клацніть правою кнопкою миші рядок -> вилучення даних події -> збережіть її як-небудь .xdl і розмістіть її вміст (це xml) на Pastebin (або десь подібному).
— Маріан

1
Привіт, тут розміщено XML ... сподіваюся, що це допоможе! dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
— K09

Відповіді:


14

Що я шукаю - це те, чому я отримую DELETE / DELETE тупик.

Здається, тупик виникає через те, що:

  1. spid 54 ecid 0отримує Uблокування оновленої сторінки оновлення ( )PAGE: 12:1:5147422
  2. spid 166 ecid 3запитує Uблокування оновлених сторінок оновлення ( ) на тій самій сторінці та блокується
  3. spid 54 ecid 2вимагає оновлення ( U) блокування сторінки на цій же сторінці ...

Сторінки попередньо вибираються для запиту із блоками оновлень, придбаними користувачем ecid 0. Це крок 1 вище. На кроці 3 дочірня нитка того ж паралельного запиту ( ecid 2) запитує той самий замок. Зазвичай це не буде проблемою. SQL Server знає ecid 0і ecid 2є потоками одного батьківського процесу. На жаль, крок 2 перешкоджає цьому і призводить до тупикової ситуації.

При цьому, вам не слід дуже сильно перейматися тим, чому виникає тупик, важливим питанням є те, як цього уникнути. Відповідь полягає в тому, щоб забезпечити ефективний шлях доступу для DELETE. У операторі потрібно знайти рядки WHERE Username = @P1 AND UserDate = @P2, тому вам слід мати індекс, введений у ці стовпці.

І звичайно, у вас є такий показник. Реальний питання чому ваші проблеми почалися відбуваються після додавання відфільтрованих індексів.

Відповідь на це - додаткова інформація стовпця потрібна для пошуку відфільтрованих рядків індексу для видалення (та для перевірки їх предикатів). Якщо в запиті використовується вузький план виконання / за рядком , механізм виконання не може отримати додаткові стовпці оператора Clustered Index Delete, як це було б у плані широкого / за індексом.

Більш детальну інформацію про це та приклад роботи можна знайти в цій публікації в блозі .

У цьому випадку інформація стовпців повинна надходити з частини плану праворуч від кластерного індексу видалення, і тому використовується паралельне сканування кластерного індексу, і ви отримуєте повільний запит з високим потенціалом тупикової ситуації.

Відповідь полягає в тому, щоб зробити одне з наступного:

  1. Видаліть відфільтровані індекси
  2. Додайте відфільтрований індексний ключ / додайте / присудок стовпців до існуючого індексу імені / дати
  3. Складайте широкий план оновлення (жоден підтримуваний спосіб зробити це)
  4. Запустити запит під ізоляцією знімка (не RCSI)

Варіант 2 був би моїм сильним уподобанням.

Варіант 4 (дякую Джеку Дугласу) має перевагу в усуненні тупикових ситуацій, і він не повинен спричиняти жодних "конфліктів при оновленні", враховуючи розрізнений характер змін, але він вимагає включення знімків знімків на рівні бази даних, явно змінюючи рівень ізоляції, і не виправити основну проблему : ви все одно закінчите марнотратне сканування паралельної таблиці, де приємне прагнення до індексу - те, що ви дійсно хочете.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.