L'unico modo portatile per ottenere la coerenza tra stanze e tag e assicurarsi che le stanze non vengano mai restituite dopo che sono state eliminate è bloccarle con SELECT FOR UPDATE
.
Tuttavia in alcuni sistemi il blocco è un effetto collaterale del controllo della concorrenza e si ottengono gli stessi risultati senza specificare FOR UPDATE
esplicitamente.
Per risolvere questo problema, il thread 1 dovrebbe SELECT id FROM rooms FOR UPDATE
, impedendo così al Thread 2 di eliminare da rooms
fino a quando il thread 1 non è terminato. È corretto?
Dipende dal controllo di concorrenza utilizzato dal tuo sistema di database.
-
MyISAM
inMySQL
(e molti altri vecchi sistemi) blocca l'intera tabella per la durata di una query. -
In
SQL Server
,SELECT
le query inseriscono blocchi condivisi sui record/pagine/tabelle che hanno esaminato, mentreDML
le query inseriscono blocchi di aggiornamento (che in seguito vengono promossi a blocchi esclusivi o retrocessi a blocchi condivisi). I lucchetti esclusivi non sono compatibili con i lucchetti condivisi, quindi oSELECT
oDELETE
la query si bloccherà fino al commit di un'altra sessione. -
Nei database che utilizzano
MVCC
(comeOracle
,PostgreSQL
,MySQL
conInnoDB
), unDML
query crea una copia del record (in un modo o nell'altro) e generalmente i lettori non bloccano gli scrittori e viceversa. Per questi database, unSELECT FOR UPDATE
sarebbe utile:bloccherebbe siaSELECT
o ilDELETE
query fino a quando un'altra sessione non viene eseguita, proprio comeSQL Server
fa.
Quando si dovrebbe usare REPEATABLE_READ
isolamento della transazione rispetto a READ_COMMITTED
con SELECT ... FOR UPDATE
?
In genere, REPEATABLE READ
non vieta le righe fantasma (righe apparse o scomparse in un'altra transazione, anziché essere modificate)
-
In
Oracle
e precedentiPostgreSQL
versioni,REPEATABLE READ
è in realtà un sinonimo diSERIALIZABLE
. Fondamentalmente, ciò significa che la transazione non vede le modifiche apportate dopo che è stata avviata. Quindi, in questa configurazione, l'ultimoThread 1
query restituirà la stanza come se non fosse mai stata eliminata (che potrebbe essere o meno ciò che volevi). Se non vuoi mostrare le stanze dopo che sono state cancellate, dovresti bloccare le righe conSELECT FOR UPDATE
-
In
InnoDB
,REPEATABLE READ
eSERIALIZABLE
sono cose diverse:lettori inSERIALIZABLE
la modalità imposta i blocchi del tasto successivo sui record che valuta, prevenendo efficacemente il simultaneoDML
su di essi. Quindi non hai bisogno di unSELECT FOR UPDATE
in modalità serializzabile, ma ne hanno bisogno inREPEATABLE READ
oREAD COMMITED
.
Nota che lo standard sulle modalità di isolamento prescrive di non vedere alcune stranezze nelle tue query ma non definisce come (con blocco o con MVCC
o altro).
Quando dico "non hai bisogno di SELECT FOR UPDATE
" Avrei davvero dovuto aggiungere "a causa degli effetti collaterali di alcune implementazioni del motore di database".