sql >> Databasteknik >  >> RDS >> Sqlserver

Undvika SQL-låslägen med frågejustering:Råd från Brent Ozar

Som en del av Quests Databas Training Days Fall Series presenterade Brent Ozar, Microsoft Certified Master en handledning om "Avoiding dödlägen med Query Tuning." Programmet fokuserade på de tre samtidiga problem som uppstår i SQL Server, tre sätt att fixa dem och ett sätt som verkar fixa dem, men det gör det verkligen inte.

Samtidighetsproblem:Låsning, blockering och dödlägen i SQL Server

Vad är samtidighetsproblem? De inträffar när frågor försöker undvika konflikter med varandra över databasobjekt som tabeller. De är:

  • Låsning – Frågor gör detta hela tiden för att förhindra att andra frågor använder en tabell samtidigt. Detta är en normal databasoperation.
  • Blockerar  – Detta inträffar när en fråga har ett normalt lås, men en annan fråga försöker få samma lås. Den andra frågan måste vänta så länge som behövs för att den första frågan ska släppa låset. Beroende på typen av den första frågan kan den andra vänta en mycket kort tid eller mycket lång tid. Det är de långa väntetiderna som verkligen påverkar prestandan.
  • Låsning – Dödläge uppstår när en fråga tar ett lås, en annan fråga tar ett annat lås och sedan vill var och en skaffa den andras lås. SQL Server löser detta genom att utse en av frågorna som offer och döda den för att bryta avståndet. Även om en av frågorna kan fortsätta har detta också en inverkan på prestandan.

Åtgärda samtidighetsproblem

Oavsett om du upplever blockeringar eller dödlägen i SQL Server, finns det sätt att åtgärda samtidighetsproblem. Brent presenterade dessa tre metoder och ägnade större delen av resten av sessionen åt att fokusera på den andra – att fixa dålig kod.

  1. Ha tillräckligt med index för att göra dina frågor snabba, men inte så många att de saktar ner genom att få frågor att hålla fler låsningar under längre tid
  2. Justera din transaktionskod så att frågor fungerar genom tabeller i samma förutsägbara ordning varje gång
  3. Använd rätt isoleringsnivå för din applikations behov

När han hoppade in i den praktiska delen av programmet, kommenterade Brent att använda NOLOCK-satser för blockering och låsning. Han varnade för att NOLOCK inte riktigt löser dessa problem eftersom den förlitar sig på "smutsiga läsningar" - i huvudsak ignorerar den andra frågors radlås.

I sin demonstration av detta med hjälp av Stack Overflow-databasen skapade han en enkel fråga som letade efter och räknade personer som heter "Alex." Sedan skapade han en annan fråga som skulle köra en uppdatering på personer som är inte heter Alex – inga infogningar eller raderingar av poster. Den ena frågan ska inte ha något att göra med den andra. Men att köra dem tillsammans leder till olika resultat i antalet personer som heter Alex. Detta beror på att NOLOCK låter dig se data som inte har begåtts, vilket leder till slumpmässiga resultat som du inte kan förutsäga. Det händer bara samtidigt.

Uppenbarligen behövs en bättre fix för blockering och låsning i SQL Server som inte leder till slumpmässiga och oförutsägbara resultat.

En bättre lösning för SQL-deadlocks

Brent visade sedan hur man fixar ett dödläge genom att ändra koden som orsakar det. Hans första demo visade en enkel situation som involverade två bord så att publiken kunde se ett dödläge i slow motion medan det hände. Eftersom SQL Server letar efter dödlägen var 5:e sekund och dödar den fråga som är lättast att återställa, kunde vi se dödlägesoffret dyka upp.

I en enkel situation gäller det mest allmänna rådet, och det är att röra tabellerna i samma ordning varje gång när man konstruerar frågor. Detta kommer i allmänhet att förhindra att frågor låser varandra.

Vad sägs om mer komplexa frågor? För detta scenario använde Brent en mer realistisk situation som lätt kan uppstå på Stack Overflow där två personer röstar upp varandras frågor. Eftersom samma användare är involverade i båda transaktionerna orsakar detta ett dödläge.

Här räcker det inte att arbeta igenom varje bord i samma ordning varje gång, utan det är också nödvändigt att minimera antalet gånger varje bord berörs. Som Brent förklarade det kan korrigeringen involvera någon ful kod som gör att frågorna blockeras, men åtminstone inte dödläge. I det här fallet är ett block med kort varaktighet som gör att båda frågorna kan köras till slut bättre än ett dödläge som avslutar en av dem.

Ingen vill ändra kod i hundratals frågor, så fokusera på de som ständigt låser sig, ta bort alla onödiga rader från transaktionen och var inte rädd för att införa ett block för att undvika ett dödläge.


  1. 3 sätt att lista alla triggers för en given tabell i PostgreSQL

  2. Partitioneringsförbättringar i PostgreSQL 11

  3. ExecuteNonQuery:Anslutningsegenskapen har inte initierats.

  4. Installera PDO-drivrutiner för PostgreSQL på Mac (med Zend för eclipse)