Relazione dei livelli di isolamento della transazione con i blocchi sulla tabella


105

Ho letto circa 4 livelli di isolamento:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

Voglio capire il blocco che ogni isolamento di transazione assume sul tavolo

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

di seguito sono riportati i tre fenomeni che possono verificarsi nell'isolamento della transazione
Lettura sporca - nessun blocco Lettura non
ripetibile - nessuna lettura sporca come blocco sui dati salvati Lettura
fantasma - blocco sul blocco di sql (che viene selezionato utilizzando la query di selezione)

Voglio capire dove definiamo questi livelli di isolamento: solo a livello jdbc / hibernate o anche in DB

PS: ho esaminato i collegamenti nei livelli di isolamento in Oracle , ma sembrano goffi e parlano su database specifici


3
Dipende completamente dal database. Database diversi possono utilizzare algoritmi diversi per i livelli di isolamento. Alcuni possono utilizzare MVCC (nessun blocco su query selezionate), alcuni utilizzano un rigoroso blocco a 2 fasi (blocchi condivisi ed esclusivi).
tè brb

Risposte:


157

Voglio capire il blocco che ogni isolamento di transazione assume sul tavolo

Ad esempio, hai 3 processi simultanei A, B e C. A avvia una transazione, scrive i dati e esegue il commit / rollback (a seconda dei risultati). B esegue solo SELECTun'istruzione per leggere i dati. C legge e aggiorna i dati. Tutti questi processi funzionano sullo stesso tavolo T.

  • LEGGI UNCOMMITTED - nessun blocco sul tavolo. È possibile leggere i dati nella tabella mentre si scrive su di essa. Ciò significa che A scrive i dati (non salvati) e B può leggere questi dati non salvati e utilizzarli (per qualsiasi scopo). Se A esegue un rollback, B ha comunque letto i dati e li ha utilizzati. Questo è il modo più veloce ma più insicuro di lavorare con i dati poiché può portare a buchi di dati in tabelle non correlate fisicamente (sì, due tabelle possono essere correlate logicamente ma non fisicamente nelle app del mondo reale = \).
  • READ COMMITTED - blocca i dati salvati. Puoi leggere i dati che sono stati solo salvati. Ciò significa che A scrive i dati e B non può leggere i dati salvati da A finché A non esegue un commit. Il problema qui è che C può aggiornare i dati che sono stati letti e utilizzati sul client B e B non avrà i dati aggiornati.
  • REPEATABLE READ - blocca un blocco di SQL (che viene selezionato utilizzando la query di selezione). Ciò significa che B legge i dati in determinate condizioni WHERE aField > 10 AND aField < 20, ad esempio A inserisce i dati in cui il aFieldvalore è compreso tra 10 e 20, quindi B legge di nuovo i dati e ottiene un risultato diverso.
  • SERIALIZZABILE : blocca una tabella completa (su cui viene attivata la query di selezione). Ciò significa che B legge i dati e nessun'altra transazione può modificare i dati sulla tabella. Questo è il modo più sicuro ma più lento per lavorare con i dati. Inoltre, poiché una semplice operazione di lettura blocca la tabella , ciò può portare a gravi problemi in produzione: immagina che la tabella T sia una tabella Fattura, l'utente X vuole conoscere le fatture del giorno e l'utente Y vuole creare una nuova fattura, quindi mentre X esegue la lettura delle fatture, Y non può aggiungere una nuova fattura (e quando si tratta di soldi, le persone si arrabbiano davvero, specialmente i capi).

Voglio capire dove definiamo questi livelli di isolamento: solo a livello JDBC / ibernazione o anche in DB

Usando JDBC, lo definisci usando Connection#setTransactionIsolation.

Utilizzando Hibernate:

<property name="hibernate.connection.isolation">2</property>

Dove

  • 1: READ UNCOMMITTED
  • 2: LEGGI IMPEGNATO
  • 4: REPEATABLE READ
  • 8: SERIALIZZABILE

La configurazione di ibernazione è presa da qui (scusate, è in spagnolo).

A proposito, puoi anche impostare il livello di isolamento su RDBMS:

e ancora e ancora ...


docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Solo per aggiungere per Oracle: è possibile impostare il livello di isolamento di una transazione utilizzando una di queste istruzioni all'inizio di una transazione: SET TRANSACTION ISOLATION LIVELLO DI LETTURA IMPEGNATO; IMPOSTARE IL LIVELLO DI ISOLAMENTO DELLA TRANSAZIONE SERIALIZZABILE; SET TRANSACTION READ ONLY;
Studente

2
Inoltre, per risparmiare il collegamento in rete e il costo di elaborazione dell'inizio di ciascuna transazione con un'istruzione SET TRANSACTION, è possibile utilizzare l'istruzione ALTER SESSION per impostare il livello di isolamento della transazione per tutte le transazioni successive: ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
Studente

12
Per quanto riguarda REPEATABLE READ, penso che un esempio migliore per dimostrarlo sia il seguente: B avvia una transazione, legge i dati sul blocco di sql DOVE aField> 10 AND aField <20, quei dati sono bloccati fino al termine della transazione. A prova ad aggiornare quei dati ma attende a causa del blocco. Ora, quando B leggerà di nuovo quei dati nella stessa transazione, è garantito che leggerà gli stessi dati, perché è bloccato. Correggimi se sbaglio.
BornToCode

1
@LuiggiMendoza Come concetto generale, i livelli di isolamento riguardano solo Lettura sporca , Lettura non ripetibile e Righe fantasma . I blocchi (S2PL) o MVCC sono implementazioni per diversi fornitori.
tè brb

4
@LuiggiMendoza - non sono stato preciso, dovrebbe essere così - i dati che B ha letto non vengono modificati, ma le conseguenti selezioni effettuate da B potrebbero restituire più righe. Questo perché A non può modificare le righe già lette da B finché A non le rilascia. Tuttavia A può inserire nuove righe che qualificano la condizione where (e quindi la prossima volta che A eseguirà una selezione otterrà un risultato diverso con più righe: una lettura fantasma).
BornToCode

9

Come dice brb tea, dipende dall'implementazione del database e dall'algoritmo che usano: MVCC o Two Phase Locking.

CUBRID (RDBMS open source) spiega l'idea di questi due algoritmi:

  • Bloccaggio bifase (2PL)

Il primo è quando la transazione T2 tenta di modificare il record A, sa che la transazione T1 ha già modificato il record A e attende fino al completamento della transazione T1 perché la transazione T2 non può sapere se la transazione T1 verrà confermata o rollata indietro. Questo metodo è chiamato bloccaggio a due fasi (2PL).

  • Controllo della concorrenza multi-versione (MVCC)

L'altro è consentire a ciascuna di esse, transazioni T1 e T2, di avere le proprie versioni modificate. Anche quando la transazione T1 ha modificato il record A da 1 a 2, la transazione T1 lascia il valore originale 1 così com'è e scrive che la versione della transazione T1 del record A è 2. Quindi, la seguente transazione T2 cambia il record A da 1 a 3, non da 2 a 4, e scrive che la versione della transazione T2 del record A è 3.

Quando viene eseguito il rollback della transazione T1, non importa se il 2, la versione della transazione T1, non viene applicato al record A. Dopodiché, se viene eseguito il commit della transazione T2, la 3, la versione della transazione T2, verrà applicata al record A. Se viene eseguito il commit della transazione T1 prima della transazione T2, il record A viene modificato in 2 e quindi in 3 al momento del commit della transazione T2. Lo stato finale del database è identico allo stato di esecuzione di ciascuna transazione in modo indipendente, senza alcun impatto su altre transazioni. Pertanto, soddisfa la proprietà ACID. Questo metodo è denominato Multi-version concurrency control (MVCC).

L'MVCC consente modifiche simultanee al costo di un maggiore overhead in memoria (perché deve mantenere versioni diverse degli stessi dati) e di calcolo (nel livello REPETEABLE_READ non puoi perdere gli aggiornamenti quindi deve controllare le versioni dei dati, come Hiberate fa con Optimistick Locking ).

In 2PL i livelli di isolamento delle transazioni controllano quanto segue :

  • Indica se i blocchi vengono presi quando i dati vengono letti e che tipo di blocchi vengono richiesti.

  • Per quanto tempo vengono mantenuti i blocchi di lettura.

  • Se un'operazione di lettura che fa riferimento a righe modificate da un'altra transazione:

    • Blocca finché non viene liberato il blocco esclusivo sulla riga.

    • Recupera la versione confermata della riga che esisteva al momento in cui è iniziata l'istruzione o la transazione.

    • Leggere la modifica dei dati non salvata.

La scelta di un livello di isolamento della transazione non influisce sui blocchi acquisiti per proteggere le modifiche ai dati. Una transazione ottiene sempre un blocco esclusivo su tutti i dati che modifica e mantiene tale blocco fino al completamento della transazione, indipendentemente dal livello di isolamento impostato per quella transazione. Per le operazioni di lettura, i livelli di isolamento delle transazioni definiscono principalmente il livello di protezione dagli effetti delle modifiche apportate da altre transazioni.

Un livello di isolamento inferiore aumenta la capacità di molti utenti di accedere ai dati contemporaneamente, ma aumenta il numero di effetti di concorrenza , come letture sporche o aggiornamenti persi, che gli utenti potrebbero incontrare.

Esempi concreti della relazione tra blocchi e livelli di isolamento in SQL Server (utilizzare 2PL tranne su READ_COMMITED con READ_COMMITTED_SNAPSHOT = ON)

  • READ_UNCOMMITED: non emette blocchi condivisi per impedire ad altre transazioni di modificare i dati letti dalla transazione corrente. Le transazioni READ UNCOMMITTED non sono inoltre bloccate da blocchi esclusivi che impedirebbero alla transazione corrente di leggere le righe che sono state modificate ma non sottoposte a commit da altre transazioni. [...]

  • READ_COMMITED:

    • Se READ_COMMITTED_SNAPSHOT è impostato su OFF (impostazione predefinita): utilizza blocchi condivisi per impedire ad altre transazioni di modificare le righe mentre la transazione corrente esegue un'operazione di lettura. I blocchi condivisi impediscono inoltre all'istruzione di leggere le righe modificate da altre transazioni fino al completamento dell'altra transazione. [...] I blocchi di riga vengono rilasciati prima che venga elaborata la riga successiva. [...]
    • Se READ_COMMITTED_SNAPSHOT è impostato su ON, il Motore di database utilizza il controllo delle versioni delle righe per presentare a ciascuna istruzione un'istantanea coerente a livello di transazione dei dati così come erano all'inizio dell'istruzione. I blocchi non vengono utilizzati per proteggere i dati dagli aggiornamenti di altre transazioni.
  • REPETEABLE_READ: i blocchi condivisi vengono inseriti su tutti i dati letti da ciascuna istruzione nella transazione e vengono mantenuti fino al completamento della transazione.

  • SERIALIZZABILE: i blocchi dell'intervallo vengono inseriti nell'intervallo di valori chiave che corrispondono alle condizioni di ricerca di ciascuna istruzione eseguita in una transazione. [...] I blocchi dell'intervallo vengono mantenuti fino al completamento della transazione.


5

I blocchi sono sempre presi a livello di DB: -

Documento ufficiale Oracle: - Per evitare conflitti durante una transazione, un DBMS utilizza i blocchi, meccanismi per bloccare l'accesso da parte di altri ai dati a cui accede la transazione. (Notare che in modalità di commit automatico, dove ogni istruzione è una transazione, i blocchi vengono mantenuti per una sola istruzione.) Dopo che un blocco è stato impostato, rimane in vigore fino a quando la transazione non viene confermata o annullata. Ad esempio, un DBMS potrebbe bloccare una riga di una tabella fino a quando gli aggiornamenti non sono stati salvati. L'effetto di questo blocco sarebbe impedire a un utente di ottenere una lettura sporca, ovvero leggere un valore prima che sia reso permanente. (L'accesso a un valore aggiornato che non è stato sottoposto a commit è considerato una lettura sporca perché è possibile che quel valore venga riportato al valore precedente. Se si legge un valore che viene successivamente ripristinato, si avrà letto un valore non valido. )

Il modo in cui vengono impostati i blocchi è determinato da quello che viene chiamato un livello di isolamento delle transazioni, che può variare dal non supportare affatto le transazioni al supporto delle transazioni che applicano regole di accesso molto rigide.

Un esempio di un livello di isolamento della transazione è TRANSACTION_READ_COMMITTED, che non consentirà l'accesso a un valore fino a quando non sarà stato eseguito il commit. In altre parole, se il livello di isolamento della transazione è impostato su TRANSACTION_READ_COMMITTED, il DBMS non consente il verificarsi di letture sporche. L'interfaccia Connection include cinque valori che rappresentano i livelli di isolamento della transazione che è possibile utilizzare in JDBC.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.