Die einzige portable Möglichkeit, Konsistenz zwischen Räumen und Tags zu erreichen und sicherzustellen, dass Räume nach dem Löschen nie wieder zurückgegeben werden, besteht darin, sie mit SELECT FOR UPDATE zu sperren .
In einigen Systemen ist das Sperren jedoch ein Nebeneffekt der Parallelitätssteuerung, und Sie erzielen die gleichen Ergebnisse, ohne FOR UPDATE anzugeben explizit.
Um dieses Problem zu lösen, sollte Thread 1 SELECT id FROM rooms FOR UPDATE , wodurch verhindert wird, dass Thread 2 aus rooms gelöscht wird bis Thread 1 fertig ist. Ist das richtig?
Dies hängt von der Parallelitätssteuerung ab, die Ihr Datenbanksystem verwendet.
-
MyISAMinMySQL(und mehrere andere alte Systeme) sperrt die gesamte Tabelle für die Dauer einer Abfrage. -
In
SQL Server,SELECTAbfragen setzen gemeinsame Sperren auf die Datensätze / Seiten / Tabellen, die sie untersucht haben, währendDMLAbfragen platzieren Aktualisierungssperren (die später zu exklusiven Sperren hochgestuft oder zu gemeinsam genutzten Sperren herabgestuft werden). Exklusive Sperren sind mit geteilten Sperren nicht kompatibel, also entwederSELECToderDELETEDie Abfrage wird gesperrt, bis eine andere Sitzung festgeschrieben wird. -
In Datenbanken, die
MVCCverwenden (wieOracle,PostgreSQL,MySQLmitInnoDB), eineDMLquery erstellt (auf die eine oder andere Weise) eine Kopie des Datensatzes, und im Allgemeinen blockieren Leser keine Schreiber und umgekehrt. Für diese Datenbanken einSELECT FOR UPDATEwäre praktisch:es würde entwederSELECTsperren oder dasDELETEAbfrage, bis eine andere Sitzung festgeschrieben wird, genau wieSQL Servertut.
Wann sollte man REPEATABLE_READ verwenden Transaktionsisolation gegenüber READ_COMMITTED mit SELECT ... FOR UPDATE ?
Im Allgemeinen REPEATABLE READ verbietet keine Phantomzeilen (Zeilen, die in einer anderen Transaktion erschienen oder verschwunden sind, anstatt geändert zu werden)
-
In
Oracleund früherPostgreSQLVersionen,REPEATABLE READist eigentlich ein Synonym fürSERIALIZABLE. Grundsätzlich bedeutet dies, dass die Transaktion nach dem Start keine Änderungen sieht. Also in diesem Setup der letzteThread 1Die Abfrage gibt den Raum so zurück, als ob er nie gelöscht worden wäre (was Sie vielleicht wollten oder auch nicht). Wenn Sie die Räume nach dem Löschen nicht mehr anzeigen möchten, sollten Sie die Zeilen mitSELECT FOR UPDATEsperren -
In
InnoDB,REPEATABLE READundSERIALIZABLEsind verschiedene Dinge:Leser inSERIALIZABLEmode legen Next-Key-Sperren für die Datensätze fest, die sie auswerten, wodurch die gleichzeitigeDMLeffektiv verhindert wird auf sie. Sie brauchen also keinSELECT FOR UPDATEim serialisierbaren Modus, benötigen sie aber inREPEATABLE READoderREAD COMMITED.
Beachten Sie, dass der Standard zu Isolationsmodi vorschreibt, dass Sie bestimmte Macken in Ihren Abfragen nicht sehen, aber nicht definiert, wie (mit Sperren oder mit MVCC). oder anderweitig).
Wenn ich sage "Du brauchst SELECT FOR UPDATE nicht " Ich hätte wirklich "aufgrund von Nebeneffekten bestimmter Datenbank-Engine-Implementierungen" hinzufügen sollen.