Mysql
 sql >> Database >  >> RDS >> Mysql

Quando usare SELEZIONA... PER AGGIORNARE?

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 in MySQL (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, mentre DML 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 o SELECT o DELETE la query si bloccherà fino al commit di un'altra sessione.

  • Nei database che utilizzano MVCC (come Oracle , PostgreSQL , MySQL con InnoDB ), un DML 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, un SELECT FOR UPDATE sarebbe utile:bloccherebbe sia SELECT o il DELETE query fino a quando un'altra sessione non viene eseguita, proprio come SQL 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 precedenti PostgreSQL versioni, REPEATABLE READ è in realtà un sinonimo di SERIALIZABLE . Fondamentalmente, ciò significa che la transazione non vede le modifiche apportate dopo che è stata avviata. Quindi, in questa configurazione, l'ultimo Thread 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 con SELECT FOR UPDATE

  • In InnoDB , REPEATABLE READ e SERIALIZABLE sono cose diverse:lettori in SERIALIZABLE la modalità imposta i blocchi del tasto successivo sui record che valuta, prevenendo efficacemente il simultaneo DML su di essi. Quindi non hai bisogno di un SELECT FOR UPDATE in modalità serializzabile, ma ne hanno bisogno in REPEATABLE READ o READ 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".