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


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.