sql >> Databasteknik >  >> RDS >> Sqlserver

SQL Deadlock-fråga

SELECTs kan inte låsa fast med andra SELECT, eftersom de bara skaffar delade lås. Du säger att vi bör tänka på att dessa SELECT nu "kräver exklusiva läslås", men detta är inte möjligt för oss att överväga eftersom 1) det inte finns något sådant som ett exlusive read lock och 2) läsningar får inte exklusiva lås.

Men du ställer en mer allmän fråga, om enkla påståenden kan låsa sig. Svaret är ett definitivt, rungande JA . Lås förvärvas vid utförande, analyseras inte i förväg och sorteras sedan in i någon ordning. Det skulle vara omöjligt för motorn att i förväg veta vilka lås som behövs eftersom de beror på faktiska data på disken och att läsa data som motorn behöver för att ... låsa data.

Dödlägen mellan enkla påståenden (SELECT vs. UPDATE eller SELECT vs. DELETE) på grund av olika indexåtkomstordning är ganska vanliga och mycket lätta att undersöka, diagnostisera och fixa. Men observera att det finns alltid en skrivoperation involverad, eftersom läsningar inte kan blockera varandra. För den här diskussionen bör lägga till en UPDLOCK- eller XLOCK-tips till en SELECT betraktas som en skrivning. Du behöver inte ens en JOIN, ett sekundärt index kan mycket väl introducera problemet med åtkomstorder som leder till dödläge, se Läs/skriv-deadlock .

Och slutligen skriver du SELECT FROM A JOIN B eller skriva SELECT FROM B JOIN A är helt irrelevant. Frågeoptimeraren är fri att ordna om åtkomstordningen som den vill, den faktiska texten i frågan påtvingar inte exekveringsordningen på något sätt.

Uppdaterad

Jag är rädd att det inte finns något recept på kakformen. Lösningen kommer att bero från fall till fall. I slutändan är dödlägen i databasapplikationer ett faktum. Jag förstår att detta kan låta absurt, som i "vi landade på månen men vi kan inte skriva en korrekt databasapplikation", men det finns starka faktorer som i stort sett garanterar att applikationer så småningom kommer att stöta på dödlägen. Lyckliga dödlägen är den lättast att hantera fel, enkelt läs tillståndet igen, tillämpa logiken, skriv om det nya tillståndet. Nu som sagt, det finns några bra metoder som dramatiskt kan minska frekvensen av dödlägen, ner till den grad att de nästan försvunnit:

  • Försök att ha ett konsekvent åtkomstmönster för Writes . Ha tydligt definierade regler som säger saker som "en transaktion ska alltid tabeller i denna ordning:Customers -> OrderHeaders -> OrderLines .' Observera att ordern måste följas i en transaktion . Rangordna alla i princip tabeller i ditt schema och ange att alla uppdateringar måste ske i rankningsordning. Detta kokar så småningom ner till koddisciplin för den enskilda bidragsgivaren som skriver koden, eftersom den måste se till att den skriver uppdateras i rätt ordning i en transaktion.
  • Minska varaktigheten av skriverier. Den vanliga visdomen är så här:i början av transaktionen gör alla läsningar (läs det befintliga tillståndet), bearbeta sedan logiken och beräkna nya värden, skriv sedan alla uppdateringar i slutet av transaktionen. Undvik ett mönster som 'läs->skriv->logik->läs->skriv', gör istället 'läs->läs->logik->skriv->skriv'. Naturligtvis består det verkliga hantverket i hur man hanterar faktiska, verkliga, enskilda fall när man tydligen måste måste göra skriver mitt i transaktionen. En särskild notering här måste sägas om en specifik typ av transaktion:de som drivs av en kö, som per definition startar sin aktivitet genom att ta ur kö (=en skrivning) från kön. Dessa applikationer var alltid notoriskt svåra att skriva och utsatta för fel (speciellt dödlägen), som tur är finns det sätt att göra det, se Använda tabeller som köer .
  • Minska antalet läsningar. Tabellskanningar är den vanligaste orsaken till dödlägen. Korrekt indexering kommer inte bara att eliminera dödläget, utan kan också öka prestandan i processen.
  • Snapshot-isolation . Det här är det närmaste du kommer en gratis lunch när det gäller att undvika dödlägen. Jag satte det avsiktligt sist, eftersom det kan maskera andra problem (som felaktig indexering) istället för att fixa dem.

Försöker lösa det här problemet med en LockCustomerByXXX tillvägagångssätt jag är rädd att inte fungerar. Pessimistisk låsning skalar inte. Optimistisk samtidighet uppdateringar är den sätt att gå om du vill ha någon form av anständig prestanda.



  1. Hur vet jag om en databas är av hög kvalitet?

  2. Hur zippar man en fil i PL/SQL?

  3. JSON_MERGE_PATCH() vs JSON_MERGE_PRESERVE() i MySQL:Vad är skillnaden?

  4. PDF skapad med FPDF och hur man sparar och hämtar pdf:en