Blocages des verrous sur les mêmes tables temporaires dans différents processus

17

J'ai trouvé une impasse qui semble montrer quelque chose que je pensais impossible. Il y a deux processus impliqués dans l'impasse:

1. process8cf948 SPID 63

  • Exécution d'une ALTER TABLE sur la table temporaire #PB_Cost_Excp_Process_Invoices_Work.

  • Possède un verrou IX sur la table #PB_Cost_Excp_Process_Invoices_Work avec l'ID d'objet 455743580

2. process4cb3708 SPID 72

  • Exécution dans UPDATE sur la table temporaire #PB_Cost_Excp_Process_Invoices_Work qui est censée être sa propre copie unique de la table.

  • Possède un verrou Sch-M sur #PB_Cost_Excp_Process_Invoices_Work avec le même ID d'objet 455743580 !

C'est censé être impossible. Suis-je en train de manquer quelque chose? Une table #Temporary a-t-elle vraiment été réutilisée entre ces deux SPID?

Il s'agit de SQL Server 2008 R2 Service Pack 2 avec mise à jour cumulative 1 (version 10.50.4260).

La trace complète de l'impasse non modifiée est ci-dessous. Notez comment les deux processus fonctionnent tous les deux sur le même ID d'objet avec le même nom de table # 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

MISE À JOUR

La machine en question affiche 16 processeurs dans le Gestionnaire des tâches et le Gestionnaire de périphériques, donc le partitionnement des verrous est activé et les deux verrous se trouvent sur des partitions de verrouillage différentes. Je ne sais pas si le partitionnement des verrous est une cause contributive ici ou non.

J'ai également trouvé cet article intrigant sur le blog CSS SQL Server Engineers .

MISE À JOUR 2

Les tables temporaires sont supprimées à la fin de chaque procédure stockée. Ils sont créés avec le modèle create #table, modify schema, insert, update, select, and then drop. Il existe plusieurs points d'entrée pour une procédure commune qui utilise cette table temporaire #, nous avons donc un proc central qui définit les colonnes nécessaires pour appeler le proc commun. Sinon, nous devons répliquer la même définition #table dans tous les processus de point d'entrée.

Le processus est fréquemment appelé à partir de plusieurs applications clientes. Certaines applications clientes appellent ce processus à partir de plusieurs threads. D'autres l'exécutent un à la fois. Imaginez un logiciel d'inventaire / de comptabilité où le siège social traite des données pour des milliers de magasins en parallèle, tandis que les magasins exécutent eux-mêmes le même processus. Donc, si c'est un problème rare lorsque le partitionnement des verrous est activé, il ne sera pas si rare sur nos plus grandes bases de données clients.

MISE À JOUR 3 - 2012-12-19

Un autre client rencontre le même problème sur SQL Server 2012 build 11.0.2100. Je n'ai vu aucune mention d'un correctif pour ce problème dans les descriptions de mise à jour cumulative. Recherche.

MISE À JOUR 4 - 2013-02-13

Microsoft a publié le correctif de ce bogue dans les mises à jour suivantes:

Paul Williams
la source
@AaronBertrand: Non, nous ne voulons pas de mise en cache de table #temp. Ce serait déjà assez mauvais sur la même connexion - encore moins d'être réutilisé entre les processus. Je n'ai pas de fichier .xdl, juste les informations de l'indicateur de trace 1222.
Paul Williams
Nous supprimons explicitement ces tables #temp lorsque nous en avons fini avec elles.
Paul Williams
2
Je suggérerais toujours de capturer et de publier le fichier .xdl quelque part afin que d'autres puissent y regarder de plus près - il aura de bien meilleurs détails.
Aaron Bertrand
2
Je peux confirmer que le partitionnement des verrous est impliqué ici. Ces articles contiennent des détails sur l'analyse des interblocages impliquant et dus à des partitions de verrouillage. bit.ly/Ruzmym bit.ly/W7yuRK Mais je ne sais pas pourquoi les deux sessions ont affiché le même ObjectID.
Roji P Thomas
@SQLKiwi Merci d'avoir examiné le problème! Je n'ai pas pensé au verrouillage des ressources. Étant donné que c'est sur un ID d'objet, je soupçonne que ce n'est pas le cas, mais je ne fais que deviner. Le client nous signale des blocages depuis plusieurs jours. Je n'ai que 1 jour de traçage de blocage, mais je parie que c'est le blocage qu'ils connaissent. Nous ouvrons un ticket d'assistance avec Microsoft pour nous aider à le comprendre. Je mettrai à jour cette question au fur et à mesure que j'apprends.
Paul Williams

Réponses:

4

Nous avions ouvert un dossier avec Microsoft concernant ce problème. Microsoft a confirmé que ce bogue affecte également SQL Server 2012. Ils prévoient de publier le correctif dans SQL Server 2012 Service Pack 2 (non publié au moment où j'écrivais cette réponse).

Jusqu'à ce que Microsoft publie ce service pack, les utilisateurs de SQL Server 2012 peuvent contourner le problème en désactivant le partitionnement des verrous via l' indicateur de trace 1229 .

Notez que ce problème s'applique uniquement aux machines qui ont 16 processeurs ou plus.

Plus d'informations sur le partitionnement des verrous

Merci au support Microsoft! Ils ont été très rapides et serviables.

MISE À JOUR

Le bogue est résolu dans la mise à jour cumulative 2 de SQL Server 2012 pour SQL Server 2012 SP 1 .

Paul Williams
la source