Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wann sollte SELECT ... FOR UPDATE verwendet werden?

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.

  • MyISAM in MySQL (und mehrere andere alte Systeme) sperrt die gesamte Tabelle für die Dauer einer Abfrage.

  • In SQL Server , SELECT Abfragen setzen gemeinsame Sperren auf die Datensätze / Seiten / Tabellen, die sie untersucht haben, während DML Abfragen 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 entweder SELECT oder DELETE Die Abfrage wird gesperrt, bis eine andere Sitzung festgeschrieben wird.

  • In Datenbanken, die MVCC verwenden (wie Oracle , PostgreSQL , MySQL mit InnoDB ), eine DML query erstellt (auf die eine oder andere Weise) eine Kopie des Datensatzes, und im Allgemeinen blockieren Leser keine Schreiber und umgekehrt. Für diese Datenbanken ein SELECT FOR UPDATE wäre praktisch:es würde entweder SELECT sperren oder das DELETE Abfrage, bis eine andere Sitzung festgeschrieben wird, genau wie SQL Server tut.

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 Oracle und früher PostgreSQL Versionen, REPEATABLE READ ist eigentlich ein Synonym für SERIALIZABLE . Grundsätzlich bedeutet dies, dass die Transaktion nach dem Start keine Änderungen sieht. Also in diesem Setup der letzte Thread 1 Die 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 mit SELECT FOR UPDATE sperren

  • In InnoDB , REPEATABLE READ und SERIALIZABLE sind verschiedene Dinge:Leser in SERIALIZABLE mode legen Next-Key-Sperren für die Datensätze fest, die sie auswerten, wodurch die gleichzeitige DML effektiv verhindert wird auf sie. Sie brauchen also kein SELECT FOR UPDATE im serialisierbaren Modus, benötigen sie aber in REPEATABLE READ oder READ 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.