Я захожу в тупик при запуске задания SQL Server. Тупик возникает в простом операторе DELETE. Я бы подумал, что должен быть запущен запрос SELECT / UPDATE, чтобы вызвать тупик? Но похоже, что это УДАЛИТЬ / УДАЛИТЬ тупик ...
То, что я ищу, это то, почему я получаю тупик УДАЛИТЬ / УДАЛИТЬ. Это (насколько мне известно) передача в различных параметрах.
Есть идеи? Спасибо.
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
dbo.UserDetailsData
включения всех индексов? Кроме того, вы знаете, если эти операторы вызываются с одинаковыми параметрами? Учитывая, что в обоих журналах используется нулевой журнал, мне интересно, нужно ли вам всего лишь сериализовать вызовы, потому что они наступают друг на друга.Ответы:
Похоже, тупик возникает из-за:
spid 54 ecid 0
получаетU
блокировку страницы update ( )PAGE: 12:1:5147422
spid 166 ecid 3
запрашиваетU
блокировку страницы update ( ) на той же странице и блокируется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
, поэтому у вас должен быть индексированный ключ для этих столбцов.И, конечно, у вас есть такой индекс. Реальный вопрос почему ваши проблемы начались происходят после добавления отфильтрованных индексов.
Ответ на этот вопрос - дополнительная информация о столбце, необходимая для того, чтобы найти отфильтрованные строки индекса для удаления (и проверить их предикаты). Если в запросе используется узкий план выполнения для каждой строки , механизм выполнения не сможет извлечь дополнительные столбцы в операторе удаления кластеризованного индекса, как это было бы в плане широкого / для индекса.
Вы можете найти более подробную информацию об этом и рабочий пример в этом посте .
В этом случае информация о столбце должна поступать из части плана справа от удаления кластерного индекса, поэтому используется сканирование параллельного кластерного индекса, и вы получаете медленный запрос с высоким потенциалом взаимоблокировки.
Ответ заключается в том, чтобы сделать одно из следующего:
Вариант 2 будет моим сильным предпочтением.
Вариант 4 (спасибо Джеку Дугласу) имеет преимущество удаления тупиковых ситуаций и не должен вызывать никаких «конфликтов обновлений», учитывая непересекающийся характер изменений, но он требует включения изоляции моментальных снимков на уровне базы данных, явно изменяя уровень изоляции, и не решит основную проблему : вы все равно будете в конечном итоге проводить расточительное сканирование параллельных таблиц, где вам действительно нужен хороший поиск по индексу.
источник