sql >> Databasteknik >  >> RDS >> Oracle

Kommer SQL-uppdateringen att påverka dess underfråga under uppdateringskörningen?

** Redigerad **

Välja från måltabellen

Från 13.2.9.8. Underfrågor i FROM-klausulen:

Underfrågor i FROM-satsen kan returnera en skalär, kolumn, rad eller tabell. Underfrågor i FROM-satsen kan inte vara korrelerade underfrågor, såvida de inte används inom ON-satsen för en JOIN-operation.

Så, ja, du kan utföra ovanstående fråga.

Problemet

Det finns egentligen två problem här. Det finns samtidighet, eller att se till att ingen annan ändrar data under våra fötter. Detta hanteras med låsning. Att hantera den faktiska modifieringen av nya kontra gamla värden hanteras med härledda tabeller.

Låsning

I fallet med din fråga ovan, med InnoDB, utför MySQL SELECT först och skaffar ett läs (delat) lås på varje rad i tabellen individuellt. Om du hade en WHERE-sats i SELECT-satsen, skulle bara de poster du väljer låsas, där intervaller skulle göra att även luckor låses.

Ett läslås förhindrar någon annan fråga från att få skrivlås, så poster kan inte uppdateras från någon annanstans medan de är läslåsta.

Sedan får MySQL ett skrivlås (exklusivt) på var och en av posterna i tabellen individuellt. Om du hade en WHERE-sats i din UPDATE-sats, skulle bara de specifika posterna vara skrivlåsta, och igen, om WHERE-satsen valde ett intervall, skulle du ha ett intervall låst.

Varje post som hade ett läslås från föregående SELECT skulle automatiskt eskaleras till ett skrivlås.

Ett skrivlås förhindrar att andra frågor får antingen ett läs- eller skrivlås.

Du kan använda Innotop för att se detta genom att köra det i låst läge, starta en transaktion, köra frågan (men gör inte det), och du kommer att se låsen i Innotop. Du kan också se detaljerna utan Innotop med SHOW ENGINE INNODB STATUS .

Dödläge

Din fråga är sårbar för ett dödläge om två instanser kördes samtidigt. Om fråga A fick läslås, då fråga B fick läslås, skulle fråga A vänta på att fråga B:s läslås släpptes innan den kunde förvärva skrivlåsen. Fråga B kommer dock inte att släppa läslåsen förrän den är klar, och den kommer inte att slutföras om den inte kan få skrivlås. Fråga A och fråga B är i ett dödläge, och därmed ett dödläge.

Därför kanske du vill utföra ett explicit tabelllås, både för att undvika den enorma mängden postlås (som använder minne och påverkar prestandan), och för att undvika ett dödläge.

Ett alternativt tillvägagångssätt är att använda SELECT ... FÖR UPPDATERING på ditt inre SELECT. Detta börjar med skrivlås på alla rader istället för att börja med att läsa och eskalera dem.

Härledda tabeller

För den inre SELECT skapar MySQL en härledd temporär tabell. En härledd tabell är en faktisk icke-indexerad kopia av data som finns i den temporära tabellen som skapas automatiskt av MySQL (till skillnad från en temporär tabell som du uttryckligen skapar och kan lägga till index till).

Eftersom MySQL använder en härledd tabell, är det det tillfälliga gamla värdet som du refererar till i din fråga. Det finns med andra ord ingen magi här. MySQL gör det precis som du skulle göra det någon annanstans, med ett tillfälligt värde.

Du kan se den härledda tabellen genom att göra en EXPLAIN mot din UPDATE-sats (stöds i MySQL 5.6+).



  1. CAST och IsNumeric

  2. Byt namn på SA-kontot i SQL Server (T-SQL-exempel)

  3. Hur RandomBlob() fungerar i SQLite

  4. Hur returnerar man resultatuppsättning från lagrad procedur i Oracle?