Блокировки от блокировок на одних и тех же временных таблицах в разных процессах

17

Я нашел тупик, который, кажется, показывает то, что я считал невозможным. В тупик вовлечены два процесса:

1. process8cf948 SPID 63

  • Выполнение ALTER TABLE для временной таблицы #PB_Cost_Excp_Process_Invoices_Work.

  • Владеет IX блокировкой таблицы #PB_Cost_Excp_Process_Invoices_Work с идентификатором объекта 455743580

2. process4cb3708 SPID 72

  • Выполнение в UPDATE для временной таблицы #PB_Cost_Excp_Process_Invoices_Work, которая должна быть собственной уникальной копией таблицы.

  • Владеет блокировкой Sch-M на #PB_Cost_Excp_Process_Invoices_Work с тем же идентификатором объекта 455743580 !

Это должно быть невозможно. Я что-то пропустил? Действительно ли между этими двумя SPID-таблицами действительно использовалась # Временная таблица?

Это на SQL Server 2008 R2 с пакетом обновления 2 с накопительным обновлением 1 (версия 10.50.4260).

Полный неизмененный след тупика ниже. Обратите внимание, что оба процесса работают с одним и тем же идентификатором объекта с одинаковым именем таблицы # PB_Cost_Excp_Process_Invoices_Work_SNIP_0000000D8519:

12/14/2012 13:46:03,spid23s,Unknown,waiter id=process8cf948 mode=X requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process4cb3708 mode=Sch-M
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=0 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock371705d00 mode=Sch-M associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,waiter id=process4cb3708 mode=Sch-M requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process8cf948 mode=IX
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=3 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock3139b4780 mode=IX associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,resource-list
12/14/2012 13:46:03,spid23s,Unknown,Proc [Database Id = 8 Object Id = 1857974987]
12/14/2012 13:46:03,spid23s,Unknown,inputbuf
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Submit_SP @SiteKey, @PWDate
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.DR_SubmitPaperwork_SP line=174 stmtstart=12912 stmtend=13018 sqlhandle=0x03000800cb72be6e500434018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Create_SP

    -- Clean up work table
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Submit_SP line=138 stmtstart=11890 stmtend=12012 sqlhandle=0x03000800428c1f1950f833018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,UPDATE #PB_Cost_Excp_Process_Invoices_Work
    SET PBCEPrcInv_RtlPkg_Item_Quantity = RtlPkg_Item_Quantity
    FROM #PB_Cost_Excp_Process_Invoices_Work
        INNER JOIN Item_Packages (NOLOCK)
            ON PBCEPrcInv_ItemPkg_Key = ItemPkg_Key
        INNER JOIN Retail_Packages (NOLOCK)
            ON ItemPkg_RtlPkg_Key = RtlPkg_Key

    -- Lookup pricebook cost
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Create_SP line=25 stmtstart=2394 stmtend=3050 sqlhandle=0x030008003a082846321f46018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,executionStack
12/14/2012 13:46:03,spid23s,Unknown,process id=process8cf948 taskpriority=0 logused=0 waitresource=OBJECT: 2:455743580:0  waittime=3739 ownerId=707053534 transactionname=UPDATE lasttranstarted=2012-12-14T13:45:59.327 XDES=0x3c4502930 lockMode=X schedulerid=4 kpid=7276 status=suspended spid=72 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2012-12-14T13:45:58.337 lastbatchcompleted=2012-12-14T13:45:58.337 clientapp=PDI WCF Services - pdidb01-PDIMaster.cfg hostname=PDIWEB01 hostpid=2084 loginname=pdiuser isolationlevel=read committed (2) xactid=707053534 currentdb=8 lockTimeout=4294967295 clientoption1=673316896 clientoption2=128568
12/14/2012 13:46:03,spid23s,Unknown,Proc [Database Id = 8 Object Id = 1857974987]
12/14/2012 13:46:03,spid23s,Unknown,inputbuf
12/14/2012 13:46:03,spid23s,Unknown,EXEC PB_ProcessExc_Costs_Submit_SP @SiteKey, @PWDate
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.DR_SubmitPaperwork_SP line=174 stmtstart=12912 stmtend=13018 sqlhandle=0x03000800cb72be6e500434018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,EXEC dbo.PB_ProcessExc_Costs_CreateInvoiceWorkTable_SP
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_Submit_SP line=58 stmtstart=5782 stmtend=5894 sqlhandle=0x03000800428c1f1950f833018da000000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,ALTER TABLE #PB_Cost_Excp_Process_Invoices_Work DROP COLUMN PBCEPrcInv_Filler
12/14/2012 13:46:03,spid23s,Unknown,frame procname=PDICompany_218_01.dbo.PB_ProcessExc_Costs_CreateInvoiceWorkTable_SP line=50 stmtstart=5382 stmtend=5538 sqlhandle=0x0300080025d75a14ffff4701969f00000100000000000000
12/14/2012 13:46:03,spid23s,Unknown,executionStack
12/14/2012 13:46:03,spid23s,Unknown,process id=process4cb3708 taskpriority=0 logused=0 waitresource=OBJECT: 2:455743580:3  waittime=3739 ownerId=707052778 transactionname=ALTER TABLE lasttranstarted=2012-12-14T13:45:58.517 XDES=0x5f48bce80 lockMode=Sch-M schedulerid=6 kpid=7212 status=suspended spid=63 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2012-12-14T13:45:58.513 lastbatchcompleted=2012-12-14T13:45:58.513 clientapp=PDI WCF Services - pdidb01-PDIMaster.cfg hostname=PDIWEB01 hostpid=2084 loginname=pdiuser isolationlevel=read committed (2) xactid=707052778 currentdb=2 lockTimeout=4294967295 clientoption1=673316896 clientoption2=128568
12/14/2012 13:46:03,spid23s,Unknown,process-list
12/14/2012 13:46:03,spid23s,Unknown,deadlock victim=process4cb3708
12/14/2012 13:46:03,spid23s,Unknown,deadlock-list

ОБНОВИТЬ

Рассматриваемая машина показывает 16 процессоров в диспетчере задач и диспетчере устройств, поэтому разделение блокировки включено, и две блокировки находятся на разных разделах блокировки. Я не знаю, является ли разделение блокировки причиной или нет.

Я также нашел этот интригующий пост в блоге CSS SQL Server Engineers .

ОБНОВЛЕНИЕ 2

Временные таблицы удаляются в конце каждой хранимой процедуры. Они создаются с шаблоном create #table, изменяют схему, вставляют, обновляют, выбирают и затем удаляют. Существует несколько точек входа в общую процедуру, которая использует эту временную таблицу, поэтому у нас есть центральный процесс, который устанавливает столбцы, необходимые для вызова общего процесса. В противном случае нам пришлось бы тиражировать одно и то же определение #table во всех процессах точки входа.

Процесс часто вызывается из нескольких клиентских приложений. Некоторые клиентские приложения вызывают этот процесс из нескольких потоков. Другие запускают его по одному. Подумайте о программном обеспечении для инвентаризации / бухгалтерского учета, где домашний офис обрабатывает данные для тысяч магазинов параллельно, в то время как магазины сами выполняют тот же процесс. Так что, если это редкая проблема, когда включена блокировка разделов, она не будет такой редкой в ​​наших крупных клиентских базах данных.

ОБНОВЛЕНИЕ 3 - 2012-12-19

У другого клиента возникла та же проблема с SQL Server 2012 build 11.0.2100. Я не видел упоминаний об исправлении этой проблемы в описаниях накопительного обновления. Исследуя.

ОБНОВЛЕНИЕ 4 - 2013-02-13

Microsoft выпустила исправление для этой ошибки в следующих обновлениях:

Пол Уильямс
источник
@AaronBertrand: Нет, нам не нужно кэширование #temp таблицы. Это было бы достаточно плохо для одной и той же связи - гораздо реже повторного использования между процессами. У меня нет файла .xdl, только информация о флаге трассировки 1222.
Пол Уильямс
Мы явно отбрасываем эти таблицы #temp, когда закончим с ними.
Пол Уильямс
2
Я бы по-прежнему предлагал снимать и публиковать файл .xdl где-нибудь, чтобы другие могли взглянуть поближе - он будет гораздо лучше детализирован.
Аарон Бертран
2
Я могу подтвердить, что здесь используется блокировка разделов. В этих сообщениях есть некоторые подробности об анализе взаимоблокировок, связанных с блокирующими разделами. bit.ly/Ruzmym bit.ly/W7yuRK Но я не знаю, почему обе сессии опубликовали один и тот же ObjectID.
Роджи П Томас
@SQLKiwi Спасибо, что посмотрели на проблему! Я не думал о хешировании ресурсов блокировки. Учитывая, что это на объекте ID, я подозреваю, что это не так, но я просто догадываюсь. Клиент сообщал нам о тупиках в течение нескольких дней. У меня есть только 1 день отслеживания тупиковой ситуации, но я уверен, что это тот тупик, который они испытывали. Мы открываем службу поддержки с Microsoft, чтобы помочь нам разобраться в этом. Я обновлю этот вопрос, когда узнаю больше.
Пол Уильямс

Ответы:

15

Эта точная проблема была только что объявлена ​​при возникновении взаимоблокировок при выполнении хранимой процедуры для изменения временной таблицы, если в SQL Server 2008 R2 включено разделение блокировки . Он связан с накопительным пакетом обновлений 4 для SQL Server 2008 R2 с пакетом обновления 2 (SP2) .

Наконец-то окупается чтение описаний исправлений SQL Server.

USR
источник
4

Мы открыли дело с Microsoft по этому вопросу. Microsoft подтвердила, что эта ошибка также влияет на SQL Server 2012. Они планируют выпустить исправление в SQL Server 2012 с пакетом обновления 2 (не выпущено на момент написания этого ответа).

Пока Microsoft не выпустит этот пакет обновления, пользователи SQL Server 2012 смогут обойти проблему, отключив блокировку разделов с помощью флага трассировки 1229 .

Обратите внимание, что эта проблема относится только к компьютерам с 16 или более процессорами.

Подробнее о блокировке разделов

Спасибо за поддержку Microsoft! Они были очень быстрыми и полезными.

ОБНОВИТЬ

Эта ошибка исправлена ​​в накопительном обновлении 2 для SQL Server 2012 для SQL Server 2012 с пакетом обновления 1 (SP1) .

Пол Уильямс
источник