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.
-
MyISAMinMySQL(e molti altri vecchi sistemi) blocca l'intera tabella per la durata di una query. -
In
SQL Server,SELECTle query inseriscono blocchi condivisi sui record/pagine/tabelle che hanno esaminato, mentreDMLle 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 oSELECToDELETEla query si bloccherà fino al commit di un'altra sessione. -
Nei database che utilizzano
MVCC(comeOracle,PostgreSQL,MySQLconInnoDB), unDMLquery 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 UPDATEsarebbe utile:bloccherebbe siaSELECTo ilDELETEquery fino a quando un'altra sessione non viene eseguita, proprio comeSQL Serverfa.
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
Oraclee precedentiPostgreSQLversioni,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 1query 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 READeSERIALIZABLEsono cose diverse:lettori inSERIALIZABLEla modalità imposta i blocchi del tasto successivo sui record che valuta, prevenendo efficacemente il simultaneoDMLsu di essi. Quindi non hai bisogno di unSELECT FOR UPDATEin modalità serializzabile, ma ne hanno bisogno inREPEATABLE READoREAD 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".