sql >> Database teknologi >  >> RDS >> Oracle

Vil SQL-opdatering påvirke dens underforespørgsel under opdateringskørsel?

** Redigeret **

Vælg fra måltabellen

Fra 13.2.9.8. Underforespørgsler i FROM-klausulen:

Underforespørgsler i FROM-sætningen kan returnere en skalar, kolonne, række eller tabel. Underforespørgsler i FROM-sætningen kan ikke være korrelerede underforespørgsler, medmindre de bruges i ON-sætningen af ​​en JOIN-operation.

Så ja, du kan udføre ovenstående forespørgsel.

Problemet

Der er virkelig to problemer her. Der er samtidighed eller sikring af, at ingen andre ændrer dataene under vores fødder. Dette håndteres med låsning. Håndtering af den faktiske ændring af nye kontra gamle værdier håndteres med afledte tabeller.

Låsning

I tilfælde af din forespørgsel ovenfor, med InnoDB, udfører MySQL SELECT først og erhverver en læst (delt) lås på hver række i tabellen individuelt. Hvis du havde en WHERE-sætning i SELECT-sætningen, ville kun de poster, du vælger, blive låst, hvor intervaller også ville medføre, at eventuelle huller blev låst.

En læselås forhindrer enhver anden forespørgsel i at opnå skrivelåse, så registreringer kan ikke opdateres andre steder fra, mens de er læselåste.

Derefter får MySQL en skrivelås (eksklusiv) på hver af posterne i tabellen individuelt. Hvis du havde en WHERE-sætning i din UPDATE-sætning, ville kun de specifikke poster være skrivelåst, og igen, hvis WHERE-sætningen valgte et område, ville du have et område låst.

Enhver post, der havde en læselås fra det forrige SELECT, vil automatisk blive eskaleret til en skrivelås.

En skrivelås forhindrer andre forespørgsler i at opnå enten en læse- eller skrivelås.

Du kan bruge Innotop til at se dette ved at køre det i låsetilstand, starte en transaktion, udføre forespørgslen (men ikke begå det), og du vil se låsene i Innotop. Du kan også se detaljerne uden Innotop med SHOW ENGINE INNODB STATUS .

Deadlocks

Din forespørgsel er sårbar over for en dødvande, hvis to forekomster blev kørt på samme tid. Hvis forespørgsel A fik læselåse, så fik forespørgsel B læselåse, ville forespørgsel A vente på, at forespørgsel B's læselåse blev frigivet, før den kunne opnå skrivelåsene. Forespørgsel B vil dog ikke frigive læselåsene, før den er færdig, og den afsluttes ikke, medmindre den kan erhverve skrivelåse. Forespørgsel A og forespørgsel B er i et dødvande og dermed et dødvande.

Derfor kan du ønske at udføre en eksplicit tabellås, både for at undgå den enorme mængde af registreringslåse (som bruger hukommelse og påvirker ydeevnen), og for at undgå en dødvande.

En alternativ tilgang er at bruge SELECT ... TIL OPDATERING på dit indre SELECT. Dette starter med skrivelåse på alle rækkerne i stedet for at starte med at læse og eskalere dem.

Afledte tabeller

For den indre SELECT opretter MySQL en afledt midlertidig tabel. En afledt tabel er en faktisk ikke-indekseret kopi af de data, der findes i den midlertidige tabel, der automatisk oprettes af MySQL (i modsætning til en midlertidig tabel, som du eksplicit opretter og kan tilføje indekser til).

Da MySQL bruger en afledt tabel, er det den midlertidige gamle værdi, som du henviser til i dit spørgsmål. Med andre ord, der er ingen magi her. MySQL gør det ligesom du ville gøre det andre steder, med en midlertidig værdi.

Du kan se den afledte tabel ved at lave en EXPLAIN mod din UPDATE-sætning (understøttet i MySQL 5.6+).



  1. Bruger forskellige databaser forskellige navnecitater?

  2. opret brugerdefineret funktion til datoforskel eksklusive weekender og helligdage i oracle sql

  3. onCreate() af RoomDatabase.Callback() blev ikke kaldt efter et vellykket kald til .build()

  4. pdo udarbejdede udsagn med jokertegn