sql >> Database teknologi >  >> RDS >> Sqlserver

Undgå SQL-deadlocks med forespørgselsjustering:Råd fra Brent Ozar

Som en del af Quest's Database Training Days Fall Series præsenterede Brent Ozar, Microsoft Certified Master et selvstudie om "Avoiding deadlocks with Query Tuning". Programmet fokuserede på de tre samtidige problemer, der opstår i SQL Server, tre måder at løse dem på og en måde, der ser ud til at løse dem, men det gør det i virkeligheden ikke.

Samtidighedsproblemer:Låsning, blokering og deadlocks i SQL Server

Hvad er samtidighedsproblemer? De sker, når forespørgsler forsøger at undgå konflikt med hinanden over databaseobjekter som tabeller. De er:

  • Låsning – Forespørgsler gør dette hele tiden for at forhindre andre forespørgsler i at bruge en tabel på samme tid. Dette er en normal databaseoperation.
  • Blokering  – Dette sker, når en forespørgsel har en normal lås, men en anden forespørgsel forsøger at erhverve den samme lås. Den anden forespørgsel skal vente så længe det er nødvendigt, før den første forespørgsel frigiver låsen. Afhængigt af arten af ​​den første forespørgsel, kan den anden vente meget kort tid eller meget lang tid. Det er de lange ventetider, der virkelig påvirker ydeevnen.
  • Deadlocking – Dødlåse opstår, når én forespørgsel tager en lås, en anden forespørgsel tager en anden lås, og så hver forespørgsel ønsker at erhverve den andens lås. SQL Server løser dette ved at udpege en af ​​forespørgslerne som offeret og dræbe den for at bryde standoffen. Selvom en af ​​forespørgslerne er i stand til at fortsætte, har dette også indflydelse på ydeevnen.

Løsning af samtidighedsproblemer

Uanset om du oplever blokeringer eller deadlocks i SQL Server, er der måder at løse samtidighedsproblemer på. Brent præsenterede disse tre metoder og brugte det meste af resten af ​​sessionen på at fokusere på den anden – at rette dårlig kode.

  1. Har nok indekser til at gøre dine forespørgsler hurtige, men ikke så mange, at de bremser tingene ved at få forespørgsler til at holde flere låse i længere tid
  2. Juster din transaktionskode, så forespørgsler arbejder gennem tabeller i samme forudsigelige rækkefølge hver gang
  3. Brug det rigtige isolationsniveau til din applikations behov

Da han hoppede ind i den praktiske del af programmet, kommenterede Brent at bruge NOLOCK-udsagn til blokering og deadlocking. Han advarede om, at NOLOCK ikke rigtig løser disse problemer, fordi den er afhængig af "beskidte læsninger" - i det væsentlige ignorerer den andre forespørgslers rækkelåse.

I sin demonstration af dette ved hjælp af Stack Overflow-databasen oprettede han en simpel forespørgsel, der ledte efter og talte personer ved navn "Alex." Derefter oprettede han en anden forespørgsel, der ville køre en opdatering på personer, der ikke er ved navn Alex – ingen indsættelser eller sletninger af poster. Den ene forespørgsel burde ikke have noget at gøre med den anden. Men at køre dem sammen fører til forskellige resultater i antallet af personer, der hedder Alex. Dette skyldes, at NOLOCK lader dig se data, der ikke var forpligtet, hvilket fører til tilfældige resultater, som du ikke kan forudsige. Det sker kun under samtidighed.

Det er klart, at der er behov for en bedre løsning til blokering og deadlocking i SQL Server, som ikke fører til tilfældige og uforudsigelige resultater.

En bedre løsning til SQL-deadlocks

Brent demonstrerede derefter, hvordan man fikser en dødvande ved at ændre koden, der forårsager det. Hans første demo viste en simpel situation, der involverede to borde, så publikum kunne se en dødvande i slowmotion, mens det skete. Da SQL Server leder efter dødvande hvert 5. sekund og dræber den forespørgsel, der er den nemmeste at rulle tilbage, var vi i stand til at se dødvande-offeret dukke op.

I en simpel situation gælder det mest generelle råd, og det er at røre tabellerne i samme rækkefølge hver gang, når du konstruerer forespørgsler. Dette vil generelt forhindre forespørgsler i at blokere hinanden.

Hvad med mere komplekse forespørgsler? Til dette scenarie brugte Brent en mere realistisk situation, der nemt kunne opstå på Stack Overflow, hvor to personer stemmer op på hinandens spørgsmål. Fordi de samme brugere er involveret i begge transaktioner, forårsager dette et dødvande.

Her er det ikke nok at arbejde gennem hvert bord i samme rækkefølge hver gang, men det er også nødvendigt at minimere antallet af gange, hvert bord berøres. Som Brent forklarede det, kan rettelsen involvere noget grim kode, der får forespørgslerne til at blokere, men i det mindste ikke deadlock. I dette tilfælde er en blok med kort varighed, der tillader begge forespørgsler at køre til færdiggørelse, bedre end en deadlock, der afslutter en af ​​dem.

Ingen ønsker at ændre kode i hundredvis af forespørgsler, så fokuser på dem, der konstant låser sig, fjern eventuelle unødvendige linjer fra transaktionen, og vær ikke bange for at indføre en blokering for at undgå en deadlock.


  1. Neo4j - Opret et forhold ved hjælp af Cypher

  2. Deadlocks i PostgreSQL, når du kører UPDATE

  3. Hvordan Tanh() virker i PostgreSQL

  4. Eksporter data til Excel fra Oracle Table ved hjælp af PL SQL