2.1 Leggi senza impegno

Il "livello di isolamento della transazione" si riferisce al grado di protezione fornito dai meccanismi interni del DBMS (ovvero, non richiedendo una programmazione speciale) da tutti o alcuni dei suddetti tipi di incongruenze di dati che si verificano durante l'esecuzione parallela delle transazioni. Lo standard SQL-92 definisce una scala di quattro livelli di isolamento:

  • Leggi senza impegno
  • Leggi commesso
  • Lettura ripetibile
  • Serializzabile

Il primo è il più debole, l'ultimo è il più forte, ogni successivo include tutti i precedenti.

Il livello di isolamento più basso (primo). Se diverse transazioni parallele tentano di modificare la stessa riga della tabella, la riga finale avrà un valore determinato dall'intero insieme di transazioni completate con successo. In questo caso è possibile leggere non solo dati logicamente incoerenti, ma anche dati le cui modifiche non sono state ancora registrate.

Un modo tipico per implementare questo livello di isolamento consiste nel bloccare i dati durante l'esecuzione del comando di modifica, il che garantisce che i comandi di modifica sulle stesse righe eseguiti in parallelo vengano effettivamente eseguiti in sequenza e che nessuna delle modifiche venga persa. Le transazioni di sola lettura non si bloccano mai sotto questo livello di isolamento.

2.2 Leggere il commit

La maggior parte dei DBMS industriali, in particolare Microsoft SQL Server, PostgreSQL e Oracle, utilizzano questo livello per impostazione predefinita. A questo livello viene fornita protezione contro le bozze, la lettura "sporca", tuttavia, durante l'operazione di una transazione, un'altra può essere completata con successo e le modifiche apportate da essa vengono corrette. Di conseguenza, la prima transazione funzionerà con un set di dati diverso.

L'implementazione di una lettura completa può essere basata su uno dei due approcci: blocco o controllo delle versioni.

Blocco dei dati leggibili e modificabili.

Consiste nel fatto che la transazione di scrittura blocca i dati mutabili per le transazioni di lettura operanti al livello read commit o superiore fino al suo completamento, impedendo così la lettura "sporca", e i dati bloccati dalla transazione di lettura vengono rilasciati immediatamente dopo il completamento dell'operazione SELECT(quindi, una situazione di "lettura non ripetibile" può verificarsi a un dato livello di isolamento).

Salvataggio di più versioni di righe che cambiano in parallelo.

Ogni volta che viene modificata una riga, il DBMS crea una nuova versione di questa riga, con la quale la transazione che ha modificato i dati continua a funzionare, mentre qualsiasi altra transazione di "lettura" restituisce l'ultima versione di cui è stato eseguito il commit. Il vantaggio di questo approccio è che è più veloce perché impedisce il blocco. Tuttavia, richiede, rispetto al primo, un consumo di RAM significativamente maggiore, che viene speso per l'archiviazione delle versioni di riga.

Inoltre, quando più transazioni modificano i dati in parallelo, può creare una situazione in cui diverse transazioni simultanee apportano modifiche incoerenti agli stessi dati (poiché non ci sono blocchi, nulla impedirà che ciò accada). Quindi la transazione che esegue il commit per prima salverà le sue modifiche nel database principale e le restanti transazioni parallele saranno impossibili da eseguire (poiché ciò comporterà la perdita dell'aggiornamento della prima transazione). L'unica cosa che il DBMS può fare in una situazione del genere è ripristinare il resto delle transazioni ed emettere un messaggio di errore "Il record è già stato modificato".

Un metodo di implementazione specifico viene scelto dagli sviluppatori DBMS e in alcuni casi può essere personalizzato. Quindi, per impostazione predefinita, MS SQL utilizza i blocchi, ma (nella versione 2005 e successive) quando si imposta il READ_COMMITTED_SNAPSHOTparametro del database, passa alla strategia di controllo delle versioni, Oracle inizialmente funziona solo secondo lo schema con versione. In Informix, puoi evitare conflitti tra transazioni di lettura e scrittura impostando un'opzione di configurazione USELASTCOMMITTED(a partire dalla versione 11.1) che fa in modo che la transazione di lettura riceva i dati di cui è stato eseguito il commit più recente.

2.3 Lettura ripetibile

Il livello al quale una transazione di lettura "non vede" cambia nei dati che ha letto in precedenza. Allo stesso tempo, nessun'altra transazione può modificare i dati letti dalla transazione corrente fino al suo termine.

I blocchi in modalità condivisa vengono applicati a tutti i dati letti da qualsiasi istruzione in una transazione e vengono mantenuti fino al completamento della transazione. Ciò impedisce ad altre transazioni di modificare le righe lette dalla transazione in sospeso. Tuttavia, altre transazioni possono inserire nuove righe che corrispondono alle condizioni di ricerca per le istruzioni contenute nella transazione corrente. Quando l'istruzione viene riavviata dalla transazione corrente, verranno recuperate nuove righe, risultando in una lettura fantasma.

Dato che i blocchi condivisi vengono mantenuti fino alla fine della transazione, anziché essere rilasciati alla fine di ogni istruzione, il grado di concorrenza è inferiore al livello di isolamento READ COMMITTED. Pertanto, in genere non è consigliabile utilizzare questo e livelli di transazione superiori inutilmente.

2.4 Serializzabile

Il più alto livello di isolamento; le transazioni sono completamente isolate l'una dall'altra, ognuna viene eseguita come se non ci fossero transazioni parallele. È solo a questo livello che le transazioni concorrenti non sono soggette all'effetto "lettura fantasma".

2.5 Supporto per l'isolamento delle transazioni nel DBMS reale

I DBMS transazionali non sempre supportano tutti e quattro i livelli e possono anche introdurne di aggiuntivi. Ci sono anche varie sfumature nel fornire isolamento.

Quindi, in linea di principio, Oracle non supporta il livello zero, poiché la sua implementazione delle transazioni esclude le "letture sporche" e formalmente non consente di impostare il livello di lettura ripetibile, ovvero supporta solo (per impostazione predefinita) Read committede Serializable. Allo stesso tempo, a livello di singoli comandi, garantisce effettivamente la ripetibilità di lettura (se un comando SELECTnella prima transazione seleziona un insieme di righe dal database, e in questo momento una seconda transazione parallela modifica alcune di queste righe, allora il il set di risultati ricevuto dalla prima transazione conterrà righe invariate, come se non ci fosse una seconda transazione). Oracle supporta anche le cosiddette READ-ONLYtransazioni, che corrispondono a Serializable, ma non possono modificare i dati stessi.

E Microsoft SQL Server supporta tutti e quattro i livelli di isolamento delle transazioni standard e, inoltre, il livello SNAPSHOT, in cui la transazione vede lo stato dei dati di cui è stato eseguito il commit prima dell'avvio, nonché le modifiche apportate da sola, ovvero si comporta come se ha ricevuto all'avvio, uno snapshot dei dati del DB e funziona con esso. La differenza rispetto a Serialized è che non vengono utilizzati blocchi, ma di conseguenza, il commit delle modifiche potrebbe non essere possibile se una transazione simultanea ha già modificato gli stessi dati; in questo caso, la seconda transazione, nel tentativo di esecuzione, COMMITgenererà un messaggio di errore e verrà annullata.