sql >> Databasteknik >  >> RDS >> Sqlserver

Varför låser sig denna SQL Server-fråga?

  • process 9196a8 har sida 151867 plats 174 i X-läge och vill ha sida 140302 plats 31 i S-läge
  • process 88b5b8 har sida 140302 plats 31 i X-läge och vill ha sida 151867 plats 174 i S-läge
  • de två borttagningarna körs under isolationlevel="repeatable read (3)"

Så dödläget inträffar på bordets bashög (RID-lås istället för nyckellås innebär en hög inte ett Btree). Den höga isoleringsnivån (sannolikt orsakad av DTC, att döma av det exakta namnet) gör RCSI-inställningen irrelevant.

Vilken typ är kolumnerna PARTYEXTERNALREF och PARTYTYPE? Parametrarna som skickas in är NVARCHAR (dvs. Unicode) och om kolumnerna är VARCHAR (dvs. Ascii) så beror det på reglerna för datatypsprioritet NC-indexet skulle inte användas. På grund av den inblandade tabellskanningen, tillsammans med den höga isoleringsnivån som används, är ett dödläge nästan oundvikligt.

Lösningen skulle vara att använda VARCHAR-typparametrar för @P0 och @P1 så att NC-indexet skulle utnyttjas för att undvika tabellskanningen.

Om parametrarna redan är av typen VARCHAR och du kan bekräfta från exekveringsplanen att en sökning på NC används, skulle min första fråga vara vad mer gör transaktionen, annat än raderingssatserna?

BTW, du anger bara namnet på NC-indexet men jag antar att det är på (PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID) .

Uppdatera

Eftersom din kommentar säger att kolumnerna är NVARCHAR då tabellerna skannar hypotesen är förmodligen fel. Det finns ytterligare tre möjligheter att orsaka ett dödläge som behöver undersökas:

  • alla andra uttalanden som körs av transaktionen före DELETE (detta är mest troligt)
  • alla överlappningar i raderna valda av två DELETE-satser involverade i dödläget
  • hashkollision

För de två första hypoteserna är det bara du som kan göra vad som helst just nu (undersök om de är korrekta). För det sista kan jag berätta hur du verifierar det, men det är inte trivialt. Det är osannolikt att det händer och lite svårt att bevisa, men det är möjligt. Eftersom du känner till ett dödlägesfall (bifogat XML), använd det som utredningsbas:

  • återställ en punkt-i-tid kopia av databasen med stopp kl. 2011-09-02T19:00:29.690
  • kör DBCC TRACEON(3604,-1)
  • med DBCC PAGE (, 1, 151867, 3) inspektera värdena i fack 174
  • med DBCC PAGE(, 1, 140302, 3)` kontrollera värdena på plats 31
  • kör VÄLJ %%lockres%% FRÅN PARTER DÄR PARTYEXTERNALREF =... OCH ISCOUNTERPARTY='N' och PARTYID=... och skicka in värdena som läses ovan
  • jämför de resulterande låshashvärdena, om de matchar har du en hashkollision och detta orsakade dödläget.



  1. Orakel; begränsa rader per kolumnvärde

  2. SQL HAR SUMMAGRUPPER EFTER

  3. uttalande ANVÄND @dbname fungerar inte, varför? Hur gör man det?

  4. Oracle Dynamic SQL-exempel för att infoga en post med DBMS_SQL