Le seul moyen portable d'assurer la cohérence entre les salles et les balises et de s'assurer que les salles ne sont jamais renvoyées après leur suppression est de les verrouiller avec SELECT FOR UPDATE
.
Cependant, dans certains systèmes, le verrouillage est un effet secondaire du contrôle de la concurrence et vous obtenez les mêmes résultats sans spécifier FOR UPDATE
explicitement.
Pour résoudre ce problème, le fil 1 doit
SELECT id FROM rooms FOR UPDATE
, empêchant ainsi la suppression de Thread 2 derooms
jusqu'à ce que le fil 1 soit terminé. Est-ce exact ?
Cela dépend du contrôle de concurrence que votre système de base de données utilise.
-
MyISAM
dansMySQL
(et plusieurs autres anciens systèmes) verrouille toute la table pendant la durée d'une requête. -
Dans
SQL Server
,SELECT
les requêtes placent des verrous partagés sur les enregistrements/pages/tables qu'elles ont examinés, tandis queDML
les requêtes placent des verrous de mise à jour (qui sont ensuite promus en verrous exclusifs ou rétrogradés en verrous partagés). Les verrous exclusifs sont incompatibles avec les verrous partagés, donc soitSELECT
ouDELETE
la requête se verrouillera jusqu'à ce qu'une autre session soit validée. -
Dans les bases de données qui utilisent
MVCC
(commeOracle
,PostgreSQL
,MySQL
avecInnoDB
), unDML
query crée une copie de l'enregistrement (d'une manière ou d'une autre) et généralement les lecteurs ne bloquent pas les rédacteurs et vice versa. Pour ces bases de données, unSELECT FOR UPDATE
serait pratique :cela verrouillerait soitSELECT
ou leDELETE
requête jusqu'à ce qu'une autre session soit validée, tout commeSQL Server
fait.
Quand faut-il utiliser
REPEATABLE_READ
isolation des transactions par rapport àREAD_COMMITTED
avecSELECT ... FOR UPDATE
?
Généralement, REPEATABLE READ
n'interdit pas les lignes fantômes (lignes apparues ou disparues dans une autre transaction, au lieu d'être modifiées)
-
Dans
Oracle
et versions antérieuresPostgreSQL
versions,REPEATABLE READ
est en fait synonyme deSERIALIZABLE
. En gros, cela signifie que la transaction ne voit pas les modifications apportées après son démarrage. Donc dans cette configuration, le dernierThread 1
query renverra la pièce comme si elle n'avait jamais été supprimée (ce qui peut ou non être ce que vous vouliez). Si vous ne souhaitez pas afficher les pièces après leur suppression, vous devez verrouiller les lignes avecSELECT FOR UPDATE
-
Dans
InnoDB
,REPEATABLE READ
etSERIALIZABLE
sont des choses différentes :les lecteurs dansSERIALIZABLE
le mode définit des verrous de clé suivante sur les enregistrements qu'ils évaluent, empêchant efficacement leDML
simultané sur eux. Vous n'avez donc pas besoin d'unSELECT FOR UPDATE
en mode sérialisable, mais en avez besoin enREPEATABLE READ
ouREAD COMMITED
.
Notez que la norme sur les modes d'isolation prescrit que vous ne voyez pas certaines bizarreries dans vos requêtes mais ne définit pas comment (avec verrouillage ou avec MVCC
ou autre).
Quand je dis "vous n'avez pas besoin de SELECT FOR UPDATE
" J'aurais vraiment dû ajouter "à cause des effets secondaires de l'implémentation de certains moteurs de base de données".