sql >> Database teknologi >  >> RDS >> Mysql

Hvornår skal man bruge SELECT ... TIL OPDATERING?

Den eneste bærbare måde at opnå overensstemmelse mellem rum og tags og sikre, at værelser aldrig returneres, efter at de er blevet slettet, er at låse dem med SELECT FOR UPDATE .

Men i nogle systemer er låsning en bivirkning af samtidighedskontrol, og du opnår de samme resultater uden at angive FOR UPDATE eksplicit.

For at løse dette problem skal tråd 1 SELECT id FROM rooms FOR UPDATE , og derved forhindrer Tråd 2 i at slette fra rooms indtil tråd 1 er færdig. Er det korrekt?

Dette afhænger af den samtidighedskontrol dit databasesystem bruger.

  • MyISAM i MySQL (og flere andre gamle systemer) låser hele tabellen under en forespørgsel.

  • I SQL Server , SELECT forespørgsler placerer delte låse på de poster / sider / tabeller, de har undersøgt, mens DML forespørgsler placerer opdateringslåse (som senere bliver forfremmet til eksklusive eller degraderet til delte låse). Eksklusive låse er inkompatible med delte låse, så enten SELECT eller DELETE forespørgslen låses, indtil en anden session forpligtes.

  • I databaser, der bruger MVCC (som Oracle , PostgreSQL , MySQL med InnoDB ), en DML query opretter en kopi af posten (på en eller anden måde), og generelt blokerer læsere ikke forfattere og omvendt. For disse databaser, en SELECT FOR UPDATE ville være praktisk:det ville låse enten SELECT eller DELETE forespørgsel indtil en anden session begår, ligesom SQL Server gør.

Hvornår skal man bruge REPEATABLE_READ transaktionsisolering versus READ_COMMITTED med SELECT ... FOR UPDATE ?

Generelt REPEATABLE READ forbyder ikke fantomrækker (rækker, der dukkede op eller forsvandt i en anden transaktion, i stedet for at blive ændret)

  • I Oracle og tidligere PostgreSQL versioner, REPEATABLE READ er faktisk et synonym for SERIALIZABLE . Grundlæggende betyder det, at transaktionen ikke ser ændringer foretaget efter den er startet. Så i denne opsætning, den sidste Thread 1 forespørgslen vil returnere rummet, som om det aldrig er blevet slettet (hvilket måske er, hvad du ønskede). Hvis du ikke ønsker at vise rummene efter de er blevet slettet, skal du låse rækkerne med SELECT FOR UPDATE

  • I InnoDB , REPEATABLE READ og SERIALIZABLE er forskellige ting:læsere i SERIALIZABLE tilstand indstiller næste-tastlåse på de poster, de evaluerer, hvilket effektivt forhindrer den samtidige DML på dem. Så du behøver ikke en SELECT FOR UPDATE i serialiserbar tilstand, men har brug for dem i REPEATABLE READ eller READ COMMITED .

Bemærk, at standarden for isolationstilstande foreskriver, at du ikke kan se visse særheder i dine forespørgsler, men ikke definerer hvordan (med låsning eller med MVCC eller på anden måde).

Når jeg siger "du behøver ikke SELECT FOR UPDATE " Jeg burde virkelig have tilføjet "på grund af bivirkninger af visse databasemotorimplementeringer".



  1. Henter navnet på den aktuelle funktion inde i funktionen med plpgsql

  2. Overvågning af tilgængelighed Gruppereplikasynkronisering

  3. Juster dine Avg()-resultater i SQLite med DISTINCT-søgeordet

  4. Liste over datatyper i SQL Server 2017