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.
-
MyISAMiMySQL(og flere andre gamle systemer) låser hele tabellen under en forespørgsel. -
I
SQL Server,SELECTforespørgsler placerer delte låse på de poster / sider / tabeller, de har undersøgt, mensDMLforespø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å entenSELECTellerDELETEforespørgslen låses, indtil en anden session forpligtes. -
I databaser, der bruger
MVCC(somOracle,PostgreSQL,MySQLmedInnoDB), enDMLquery opretter en kopi af posten (på en eller anden måde), og generelt blokerer læsere ikke forfattere og omvendt. For disse databaser, enSELECT FOR UPDATEville være praktisk:det ville låse entenSELECTellerDELETEforespørgsel indtil en anden session begår, ligesomSQL Servergø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
Oracleog tidligerePostgreSQLversioner,REPEATABLE READer faktisk et synonym forSERIALIZABLE. Grundlæggende betyder det, at transaktionen ikke ser ændringer foretaget efter den er startet. Så i denne opsætning, den sidsteThread 1forespø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 medSELECT FOR UPDATE -
I
InnoDB,REPEATABLE READogSERIALIZABLEer forskellige ting:læsere iSERIALIZABLEtilstand indstiller næste-tastlåse på de poster, de evaluerer, hvilket effektivt forhindrer den samtidigeDMLpå dem. Så du behøver ikke enSELECT FOR UPDATEi serialiserbar tilstand, men har brug for dem iREPEATABLE READellerREAD 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".