ISOLATION
Sintassi
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
Spiegazione
Questa istruzione imposta il livello di isolamento delle transazioni a livello globale, per la sessione corrente o per la prossima transazione:
- Con la parola chiave
GLOBAL
, l'istruzione imposta il livello di isolamento predefinito per tutte le prossime sessioni. Le sessioni esistenti non sono influenzate. - Con la parola chiave
SESSION
, l'istruzione imposta il livello di isolamento predefinito per tutte le transazioni che verranno eseguite all'interno della sessione corrente. - Se non è specificata né
SESSION
néGLOBAL
, l'istruzione imposta il livello di isolamento per la prossima transazione non ancora iniziata, eseguita all'interno della sessione corrente.
Per modificare il livello di isolamento globale predefinito occorre il permesso SUPER privilege
. Tutte le sessioni sono libere di modificare il proprio livello di isolamento (anche durante una transazione), o quello della transazione successiva.
Per impostare il livello di isolamento predefinito all'avvio del server, si usa l'opzione --transaction-isolation=liv
di mysqld nella riga di comando o in un file di configurazione. I valori di liv per questa opzione utilizzano i trattini anziché gli spazi, quindi i valori ammessi sono: READ-UNCOMMITTED
, READ-COMMITTED
, REPEATABLE-READ
e SERIALIZABLE
. Per esempio, per impostare il livello di isolamento predefinito a REPEATABLE READ
, si usano queste righe nella sezione [mysqld] di un file di configurazione:
[mysqld] transaction-isolation = REPEATABLE-READ
Per determinare i livelli di isolamento globale e di sessione a runtime, si controlla il valore della variabile di sistema tx_isolation:
SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
InnoDB supporta tutti i livelli di isolamento descritti qui utilizzando diverse strategie di locking. Il livello predefinito è REPEATABLE READ
. Per ulteriori informazioni sui lock a livello di record di InnoDB e su come li utilizza per eseguire i diversi tipi di istruzioni, si vedano https://dev.mysql.com/doc/refman/en/innodb-locking.html e https://dev.mysql.com/doc/refman/en/innodb-locks-set.html.
I prossimi paragrafi spiegano in che modo MariaDB supporta i diversi livelli di isolamento.
READ UNCOMMITTED
Le istruzioni SELECT
sono eseguite in un modo non-bloccante, ma è possibile che venga usata una vecchia versione dei record. Perciò, utilizzando questo livello di isolamento, le letture potrebbero non essere coerenti. A volte vengono chiamate "letture sporche". Per tutto il resto, questo livello di isolamento funziona come READ COMMITTED
.
READ COMMITTED
Un livello di isolamento simile a Oracle per quanto riguarda le letture coerenti (non bloccanti): tutte le letture coerenti, anche se vengono eseguite all'interno di una stessa transazione, leggono un proprio snapshot. Si veda https://dev.mysql.com/doc/refman/en/innodb-consistent-read.html.
Per le letture bloccanti (SELECT
con la clausola FOR UPDATE
o LOCK IN SHARE MODE
), InnoDB blocca solo i record degli indici, e questo permette di inserire liberamente nuove righe dopo quelle bloccate. next to
locked records. Per le istruzioni UPDATE
e DELETE
, il locking dipende dal fatto che per la ricerca utilizzi un indice univoco (ad esempio WHERE id = 100
), oppure una ricerca all'interno di un intervallo (ad esempio WHERE id > 100
). Per le ricerche su un indice univoco, InnoDB blocca solo il record interessato, non ciò che si trova prima. Per le ricerce di un intervallo di valori, InnoDB blocca tutto l'intervallo che viene scansito, usando i lock di tipo gap o next-key (gap più index-record) per impedire gli inserimenti da parte di altre sessioni negli intervalli interessati. Questo comportamento è necessario perché alcune "righe fantasma" potrebbero essere bloccate dalla replica e successivamente tornare disponibili.
Nota: In MariaDB 5.1, se il livello di isolamento è impostato a READ COMMITTED
o se la variabile di sistema innodb_locks_unsafe_for_binlog è abilitata, allora InnoDB usa il gap locking solo per verificare i vincoli di integrità delle chiavi primarie e per cercare chiavi duplicate. Inoltre, i lock sui record locks per le righe che non corrispondono alla ricerca vengono rilasciati subito dopo aver valutato la condizione WHERE
. A partire da MySQL
5.1, se si usa READ COMMITTED
o si abilita innodb_locks_unsafe_for_binlog, è necessario usare il log binario basato sulle righe.
REPEATABLE READ
E' il livello di isolamento predefinito di InnoDB. Per le letture coerenti, esiste un'importante differenza rispetto al livello READ COMMITTED
: tutte le letture coerenti che si trovano all'interno di una stessa transazione leggono lo snapshot stabilito dalla prima lettura. Questo significa che se si eseguono diverse istruzioni SELECT
non-bloccanti nella stessa transazione, esse saranno coerenti anche tra loro. Si veda https://dev.mysql.com/doc/refman/en/innodb-consistent-read.html.
Per le letture bloccanti (SELECT con clausole FOR UPDATE o LOCK IN SHARE MODE) e per le istruzioni UPDATE e DELETE, il locking dipende se si cerca un valore specifico in un indice, o un intervallo di valori. Per l'indice univoco, InnoDB blocca solo il record interessato, non ciò che viene prima. Per le altre condizioni di ricerca, InnoDB blocca l'intervallo da scansire, utilizzando i lock gap o next-key (gap più index-record) per impedire gli inserimenti da parte di altre sessioni negli intervalli interessati.
SERIALIZABLE
Questo livello è simile a REPEATABLE READ ma, se l'autocommit è disabilitato, InnoDB converte implicitamente tutte le istruzioni SELECT in SELECT ... LOCK IN SHARE MODE. Se invece è abilitato, ogni SELECT è una transazione a sé stante. Perciò si sa che è di sola lettura e può essere serializzata se eseguita come lettura consistente (non-bloccante)m cioé non deve effettuare alcun lock. Questo significa che, per poter forzare una SELECT ad acquisire un lock se le altre transazioni hanno modificato i record interessati, occorre disabilitare l'autocommit.)