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