Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Transazioni e gestione delle richieste concorrenti

Effettuare insiemi di operazioni, anche concorrenti, garantendo l'integrità del database
Effettuare insiemi di operazioni, anche concorrenti, garantendo l'integrità del database
Link copiato negli appunti

Qualunque richiesta ad un DBMS è a tutti gli effetti una transazione. Una transazione può essere interpretata come un insieme di operazioni di lettura e di scrittura sul database e costituisce l'effetto di una serie di funzioni effettuate dagli utenti.

In un database relazionale la modalità standard adottata per l'avvio e la conclusione di una transazione viene chiamata "Non Concatenata" o Autocommit. In questo tipo di approccio ogni query o aggiornamento avvia e conclude una nuova transazione. Questo è il caso di una interrogazione semplice o del richiamo di una certa vista sul DB.

Nel caso in cui abbiamo bisogno di effettuare più operazioni sul DB dipendenti tra loro, quando, ad esempio, il successo di un'operazione può compromettere a cascata quello delle precedenti, dobbiamo definire la transazione in modo più strutturato. Le operazioni devono essere eseguite in un azione atomica, non suddivisibile, bisogna che l'utente avvii e concluda la stessa utilizzando la modalità Concatenata.

Questo tipo di approccio prevede la dichiarazione dell'inizio e della fine del blocco di istruzioni. Con il comando BEGIN TRANSACTION indichiamo l'inizio della transazione.

BEGIN TRANSACTION [transaction_name]

Il blocco di istruzioni si concluderà poi con l'esito della transazione, che può essere

  • positivo COMMIT
  • negativo ROLLBACK

L'istruzione di COMMIT ha l'effetto di rendere permanente le operazioni solo quando quest'ultime sono corrette. In caso contrario il sistema le annulla come se l'utente avesse chiamato l'istruzione di ROLLBACK.

Ecco le situazioni in cui si verifica un ROLLBACK:

Errori Logici
Quando vengono immessi dati errati o violati vincoli di integrità.
Fallimenti Voluti
Quando il programmatore la invoca esplicitamente.
Forzature del Sistema
Quando il DBMS impone il fallimento di una transazione per sbloccare una situazione di "stallo".
Crash del Sistema Guasti dell'hardware
Quando ci sono problemi relativi all'hardware o c'è un blackout elettrico.

Proprietà delle Transazioni

La base di dati è una "risorsa condivisa" da più applicazioni e quindi è soggetta ad accessi concorrenti. Per rendere una transazione stabile, isolata e consistente essa deve rispettare le seguenti proprietà dette "ACID" (proprietà acide):

A - Atomicità
Dopo essere stata avviata, una transazione può terminare con successo, può abortire o può essere abortita dal DBMS dopo l'esecuzione di tutte o alcune delle sue operazioni. Ogni transazione deve essere atomica (non suddivisibile) e quindi deve eseguire tutte le sue azioni o non deve eseguirne alcuna. Il DBMS controlla la sequenza di azioni registrandole (nel "database log file") in modo che ogni qual volta una transazione deve essere abortita le sue azioni vengono annullate.
C
Questa proprietà deve garantire che una transazione non violi i vincoli di integrità. Una transazione rappresenta una trasformazione corretta dello stato del database e quindi al suo termine quest'ultimo deve trovarsi in uno stato consistente senza che si verifichino contraddizioni (inconsistency) tra i dati archiviati.
I
Una transazione non può leggere risultati intermedi di altre transazioni e quindi deve sempre "osservare" una base di dati consistente. Questo tipo di proprietà deve garantire che gli effetti di una transazione siano isolati fino al termine della stessa. Per questo ogni transazione deve essere eseguita indipendentemente dall'esecuzione delle altre transazioni.
D
Nel caso in cui un operazione abbia modificato la base di dati i suoi effetti devono essere permanenti. Questo deve avvenire in tutti i casi anche in caso di errori eccezionali.

L'atomicità e la durabilità sono garantite dal "Reliability/Recovery Manager" (Gestore dell'Affidabilità), l'Isolamento dal "Gestore della Concorrenza" e la Consistenza dal "Gestore dell'integrità a tempo di esecuzione".

Problematiche relative alla Concorrenza

La programmazione concorrente è sempre stato un problema in informatica e si è evidenziato nei sistemi operativi (con i processi che condividono memoria centrale) e nei linguaggi di programmazione (con i thread che condividono la memoria heap).

Le problematiche che si possono verificare in casi del genere sono le seguenti:

Race Contitions
Un fenomeno di corsa si verifica quando più processi effettuano concorrentemente operazioni di aggiornamento su una stessa risorsa. Per superare questo problema viene ritardata l'esecuzione di operazioni in conflitto imponendo alle transazioni di richiedere dei blocchi (detti lock) per poter effettuare le operazioni di lettura e scittura. Una
porzione di codice, che può essere eseguita solamente da un processo, viene detta "Sezione Critica
DeadLock
In questo tipo di problematica due o più processi che vogliono accedere ad una risorsa condivisa attendono tutti che un processo rilasci il controllo di una Sezione Critica così da bloccarsi vicendevolmente. In questo caso si dice che le transazioni sono poste in "mutua attesa" di risorse bloccate. Per gestire questo problema, si può adottare una
politica mirata di allocazione delle risorse o una allocazione non controllata seguita dall'aborto delle cause, per poter liberare le risorse.
Starvation
In questo tipo di problema un processo non riesce mai ad ottenere le risorse di cui necessita. Questa problematica è dipesa principalmente dalla priorità di accesso alla risorsa che il processo possiede. Può essere evitata con "tecniche di invecchiamento" che prevedono l'aumento progressivo e regolano la "priorità di accesso" del processo.

Il DBMS può trovare una soluzione a queste problematiche nei servizi di sincronizzazione che offre ogni sistema operativo ma non lo fa per due motivi principali:

Concessione di blocchi esclusivi
Per ragioni di prestazioni è necessario utilizzare lock di granularità più fine. È necessario distinguere "lock in scrittura" e "lock in lettura" perchè se un dato deve essere aggiornato non si possono concorrentemente eseguire né operazioni di scrittura e né operazioni di lettura. Ne consegue che nelle tecniche di controllo reimplementate da
un database "lock in scrittura" agiscono in modo "esclusivo" senza permettere l'accesso ad un dato da parte di altri, mentre "lock in lettura" permettono altre letture per non inibire completamente l'accesso ad un dato.
Garantire la Durabilità
Una transazione deve essere riproducibile e annulabile in caso di guasti. Il Reliability/Recovery Manager gestisce l'esecuzione delle operazioni di rispristino.

Quindi, il DBMS, per evitare che si verifichino delle anomalie, deve forzatamente implementare un modulo relativo alla gestione della concorrenza che eseguirà le transazioni garantendo il rispetto delle proprietà acide ed in particolar modo della proprietà dell'isolamento.

Anomalie delle Transazioni in un DBMS

Prima di analizzare la gestione della concorrenza in un DBMS dobbiamo rilevare, più in dettaglio, le possibili interferenze che si possono creare nell'esecuzione di diverse transazioni. Prendendo in considerazione due ipotetiche transazioni T1 e T2 che agiscono sul database avremo le possibili anomalie riguardanti il loro accesso concorrente:

Write-Write - Lost Update : Perdite di Aggiornamento
  1. T1 UPDATE Y
  2. T2 UPDATE Y
  3. La transazione T1 ROLLBACK
  4. La transazione T2 COMMIT
Read-Write - Unrepeatable Read : Letture non riproducibili
  1. T1 SELECT Y
  2. T2 UPDATE Y COMMIT
  3. La transazione T1 SELECT Y
SELECT Y T2
Write-Read - Dirty Read : Letture Fantasma
  1. T1 UPDATE Y
  2. T2 SELECT Y
  3. La transazione T1 ROLLBACK
T2

Gestione della Concorrenza

Per gestire queste anomalie bisogna aumentare il livello di isolamento che automaticamente diminuisce e regola il grado di concorrenza che un determinato dato può ottenere. I DBMS prevedono la possibilità di rilasciare i vincoli di isolamento tramite il concetto di "serializzabilità". Il DBMS nel rispettare questo concetto adotta un sistema di lock a livello di record (e non di tabella come nei sistemi operativi). I blocchi adottati sono:

Shared Locks
Vengono richiesti in caso di lettura di un record e la loro acquisizione può essere concorrente ad altre acquisizioni dello stesso tipo
Exclusive Lock
Vengono richiesti in caso di scrittura di un record e sono eseguiti in isolamento

Per la gestione delle acquisizioni di queste due tipologie di blocchi il DBMS implementa una strategia di "concessione dei lock" chiamata "Strict Two Phase Locking".

Il protocollo Strict 2PL stabilisce che:

  1. Ogni transazione deve ottenere uno Shared Lock
  2. Ogni transazione deve ottenere un Exclusive Lock
  3. Se una transazione ha acquisito un Exclusive Lock
  4. Ogni Lock acquisito da una transazione deve essere rilasciato al suo termine

Lo Strict 2PL permette solo esecuzioni seriali delle transazioni, snellisce l'esecuzione di aborto delle transazioni e risolve i problemi relativi alle perdite di aggiornamento (Lost Update) e alle letture non riproducibili (Unrepeatable Read).

Il problema relativo alle letture fantasma (Dirty Read) viene risolto adottando un'altra tipologia di Lock che nell'arco della durata di una transazione non permette la modifica del numero degli elementi che soddisfano le condizioni. I Lock vengono adottati sui predicati utilizzati nelle clausole WHERE livelli di isolamento

I livelli di isolamento previsti sono i seguenti:

READ UNCOMMITED
Con questo livello non si possono verificare solo Lost Update
READ COMMITTED
Con questo livello di isolamento si possono verificare Unrepeatable Read Dirty Read
REPEATABLE READ
Con questo livello si possono verificare solo Dirty Read
SERIALIZABLE
Grazie a questo livello si raggiunge un isolamento perfetto evitando le anomalie viste.

Il livello SERIALIZABLE non risolve tutti i problemi: la sua dichiarazione richiede un numero elevato di blocchi e aumenta la competizione tra le transazioni per l'acquisizione di blocchi. Questo peggiora le prestazioni e aumenta drasticamente il rischio di stallo. La migliore soluzione sta nell'utilizzare un pò tutti i livelli di isolamento in base alle esigenze del dato o dell'applicazione.

Ti consigliamo anche