Luca Ramundo e Izumo Spedicato

Transcript

Luca Ramundo e Izumo Spedicato
Controllo della concorrenza
Esistono delle transazioni che per loro natura richiedono tantissimo tempo e che coinvolgono una
grande quantità di record. Ciò comporta un sovraccarico del sistema perché la transazione blocca
tutti gli oggetti coinvolti, finché essa non è conclusa. Bisogna quindi conoscere bene la natura delle
operazioni da effettuare per evitare eccessivi sovraccarichi.
Approfondiamo quindi il concetto di “concurrency control”.
Innanzitutto diciamo che non esiste un sistema che dia la risposta giusta al problema della
concorrenza: essa dipende solo da quello che vogliamo ottenere.
Consideriamo un esempio: gestione di uno stock di dimensione finita (aste su ebay, prenotazione di
biglietti aerei, ...)
Le transazioni non sono istantanee: prima ci si informa sul bene.
Supponiamo che S1 esprima interesse per B1, un bene che fa parte delle pertinenze di un soggetto
S3 (la cui intenzione è quella di vendere). Se l'interesse di S1 “va a buon fine” allora B1 non è più
disponibile. In questo scenario non si hanno problemi di concorrenza.
Supponiamo ora che siano due i soggetti (S1 e S2) che esprimono interesse per il bene (la
disponibilità delle informazioni è multipla). In teoria si assume che lo scambio delle informazioni
non sia costoso; nella realtà non è così. Ad esempio l'inserimento di informazioni per l'acquisto di
un biglietto aereo richiede del tempo. Tanto più “costa” la fase di scambio delle informazioni tanto
più “pesa” la fase di competizione.
Il problema della concorrenza non ammette una soluzione ottima, ma solo ottimale.
Come fare a salvaguardare gli interessi di S3 e contemporaneamente di S1 e di S2?
Bisognerebbe tutelare gli interessi non solo di S3, ma anche degli altri due soggetti al fine di
salvaguardare l'immagine del venditore; comunque in uno scenario di concorrenza è inevitabile che
qualcuno resti escluso dalla transazione.
Anche nel database c'è competizione per l'accesso alle informazioni con un numero limitato di
risorse; pertanto è necessario che gli utenti siano strutturati in maniera gerarchica in modo da non
scontentare le figure più importanti. Si pensi ad esempio al caso in cui il direttore di un
supermercato non riesca ad accedere al proprio database perché è stato raggiunto il massimo
numero di accessi, a causa di semplici clienti.
Locking
La gestione del problema della concorrenza richiede un meccanismo di Locking.
Consideriamo in primo luogo le due istruzioni LOCK(x) e UNLOCK(x), dove x è un oggetto del
database (riga, insieme di righe, tabella, insieme di tabelle,...); la prima blocca l'accesso all'oggetto
x, mentre la seconda rilascia la risorsa. Il DBMS insieme a questi due comandi deve implementare
un sistema di concorrenza: LOCKING QUEUE (sistema a coda).
Supponiamo ora di avere più oggetti:
1. S1 ha bisogno dell'oggetto x → LOCK(x);
2. S1 ha bisogno dell'oggetto y → LOCK(y);
3. S1 lavora su x (legge o scrive);
4. S1 lavora su y;
5. S1 rilascia x → UNLOCK(x);
6. S1 rilascia y → UNLOCK(Y);
Ora S2 può procedere e ripetere lo stesso schema; questa è una situazione ottimistica, ma in realtà
l’accesso può essere concorrente.
Consideriamo ora un altro scenario:
1. S1 blocca x con un LOCK(x);
2. S2 blocca y con LOCK(y);
3. S1 ha bisogno di y, che però è stata bloccata da S2 S1 si mette in code e aspetta il rilascio
di y;
4. S2 ha bisogno di x, che però è stata bloccata da S1 S2 si mette in code e aspetta il rilascio
di x;
Questa è la tipica situazione di deadlock: nessuno dei 2 procede.
Il tipo di Locking appena introdotto è detto binary, poiché la risorsa può trovarsi solo in 2 stati
possibili:
1) bloccato;
2) sbloccato.
Per gestire la concorrenza occorre che la transazione rispetti le seguenti regole:
1) LOCK(x) deve precedere READ(x) o WRITE(x);
2) UN LOCK(x) deve seguire qualunque READ(x) o WRITE(x);
3) Non è consentito fare seguire LOCK(x) da LOCK(x);
4) UN LOCK(x) non può precedere LOCK(x).
La transazione può essere realizzata sfruttando la tecnica del Two Phases Locking:
il DBMS prima di effettuare una transazione porta tutte le operazioni di LOCKING all’inizio
mentre quelle di UNLOCKING alla fine.
Questa operazione non è adatta nel caso in cui sia coinvolto un numero elevato di oggetti del DB:
sarebbe troppo oneroso per il sistema.
Una soluzione più complessa, ma decisamente più flessibile è quella del READ/WRITE
LOCKING associata al Two Phases Locking; le istruzioni sono:
1) RL(x):
2) WL(x);
3) U(x).
In tal caso si sfrutta il fatto che l’accesso in lettura ad un’informazione non comporta problemi;
anche se vi è un certo numero di RL(x), la risorsa x può essere comunque libera.
Questa è un’analisi più dettagliata, ma consente al sistema di gestire più transazioni in parallelo.
Quello di cui si è finora discusso è la gestione della concorrenza a livello logico; tale fase deve
essere preceduta da quella concettuale. A livello concettuale, vengono fissate le regole che
definiscono le gerarchie degli utenti al fine di gestire in maniera ottimale la concorrenza.
Il DBMS di default usa il locking ottimistico costituito da 3 fasi:
1) read phase;
2) validation phase;
3) write phase.
Si parla infatti di 3 Phases Locking.
Questa tecnica comporta la copia in locale degli oggetti che vengono letti dal DB; la fase di
validation serve a controllare che i dati letti non siano stati cambiati da altri soggetti.
Luca Ramundo
Izumo Spedicato