Transazioni e controllo della concorrenza Tecniche di programmazione distribuita - responsabilità del programmatore, basso livello Alto livello - transazione sequenza di operazioni sul server, che coinvolgono un insieme di processi e/o risorse condivise, che è garantita essere atomica (dal server) in presenza di concorrenza e di guasti Metodi di controllo della concorrenza Lock Ottimistico Timestamp - ordinamento Proprietà delle transazioni tutto o niente lo operazioni sono compiute tutte con successo o se anche una sola fallisce, va ripristinato lo stato iniziale isolamento non c è interferenza con altre transazioni, non devono essere visibili effetti intermedi Transazioni Deve esistere una memoria stabile: memorizzazione permanente e ridondante Devono esistere algoritmi per gestire la ridondanza A atomicità sequenza indivisibile dall esterno C consistenza I isolamento D durata permanenza se la transizione termina con successo il cambiamento è permanente seriazzabilità non interferenza fra transazioni concorrenti commit abort annidamento se e transazioni sono annidate solo la più esterna può avere permanenza -> maggior concorrenza nello stesso livello maggiori prestazioni tolleranza ai guasti eseguire una transazione con successo eseguire una transazione con insuccesso C12.2 1
Esempio: transazioni bancarie - operazioni sulle interfacce Oggetto conto Oggetto filiale Operazioni sull interfaccia Account deposit(amount) deposita amount sul conto withdraw(amount) preleva amount dal conto getbalance() -> amount restituisce il saldo del conto setbalance(amount) pone il saldo del conto ad amount Operazioni sull interfaccia Branch create(name) -> account crea un nuovo account con il nome specificato lookup(name) -> account restituisce un puntatore al conto con il nome dato branchtotal() -> amount restituisce il totale di tutti i conti nel branch C12.3 Esempio: transazione bancaria di un cliente Transaction T: a.withdraw(100); b.deposit(100); c.withdraw(200); b.deposit(200); a, b, c variabili di tipo Account Atomicità delle transazioni - assenza di interferenza Consistenza - concorrenza multi-thread e possibile interleaving dei metodi withdraw e deposit Isolamento - effetti intermedi invisibili Durata - effetto permanente Es. Java: uso di metodi synchronized per la mutua esclusione dell accesso uno dei modi possibili per garantire l atomicità Transazioni: possono essere parte del middleware C12.4 2
Operazioni nell interfaccia Coordinator Necessità di massimizzare la concorrenza Transazioni serializzabili (serialmente equivalenti) se l esecuzione seriale e concorrente sono equivalenti Coordinatore: crea e gestisce le transazioni Interfaccia Coordinator opentransaction() -> trans; inizia una nuova transazione e restituisce un unico TID trans. L identificatore viene poi usato per le altre operazioni nella transazione closetransaction(trans) -> (commit, abort); termina la transazione: restituisce un valore commit (la transazione è completata con successo) o abort ( terminata con insuccesso) aborttransaction(trans); termina la transazione con insuccesso C12.5 Storie di vita di transazione Con successo Terminata dal cliente Terminata dal server opentransaction opentransaction opentransaction operation operation operation operation operation operation server aborts transaction operation operation operation ERROR closetransaction aborttransaction reported to client C12.6 3
Transazioni e controllo della concorrenza Gestione delle transazioni Concorrenza - Interferenza Il risultato può dipendere dai tempi di esecuzione e dalla sequenza delle operazioni - problema della perdita di aggiornamento (lost update) manipolazione dei dati non gestita correttamente e che determina la perdita di un risultato di aggiornamento - problema dell inconsistenza (retrieval disparity o inconsistent retrieval) valori dei dati non consistenti per tutte le copie se la modifica di dati condivisi non è atomica esistono copie multiple di dati il recupero di informazione può portare valori inconsistenti C12.7 Problema della perdita di aggiornamento Transazione T : balance = b.getbalance(); b.setbalance(balance*1.1); a.withdraw(balance/10) balance = b.getbalance(); $200 b.setbalance(balance*1.1); $220 a.withdraw(balance/10) $80 Transazione U : balance = b.getbalance(); b.setbalance(balance*1.1); c.withdraw(balance/10) balance = b.getbalance(); $200 b.setbalance(balance*1.1); $220 c.withdraw(balance/10) $280 C12.8 4
Problema dell inconsistenza Transazione V : a.withdraw(100) b.deposit(100) a.withdraw(100); $100 b.deposit(100) $300 Transazione W : abranch.branchtotal() total = a.getbalance() $100 total = total+b.getbalance() $300 total = total+c.getbalance() C12.9 Transazioni ed equivalenza seriale Transazioni equivalenti serialmente se l esecuzione concorrente e seriale danno lo stesso risultati Se le transazioni interferiscono si può individuare una combinazione di operazioni delle sequenze (interleaving) che sia equivalente serialmente - stesso valore delle variabili in lettura - le variabili (attributi) degli oggetti hanno lo steso valore, al termine della esecuzione perdita di aggiornamento inconsistenza uso dell equivalenza seriale lettura di valori vecchi ed uso per elaborazione esecuzione concorrente (non seriale) di lettura e aggiornamento C12.10 5
Interleaving di T ed U equivalenti serialmente Transazione T : balance = b.getbalance() b.setbalance(balance*1.1) a.withdraw(balance/10) balance = b.getbalance() $200 b.setbalance(balance*1.1) $220 a.withdraw(balance/10) $80 Transazione U : balance = b.getbalance() b.setbalance(balance*1.1) c.withdraw(balance/10) balance = b.getbalance() $220 b.setbalance(balance*1.1) $242 c.withdraw(balance/10) $278 C12.11 Interleaving di V e W serialmente equivalenti Transazione V: a.withdraw(100); b.deposit(100) a.withdraw(100); $100 b.deposit(100) $300 Transazione W: abranch.branchtotal() total = a.getbalance() $100 total = total+b.getbalance() $400 total = total+c.getbalance()... C12.12 6
Conflitto di operazioni Due operazioni sono in conflitto se il risultato (effetto) della esecuzione combinata dipende dall ordine di esecuzione read accesso oggetto write modifica Effetto: valore dell oggetto dopo l esecuzione C12.13 Regole di conflitto di operazioni read e write Operazioni di diverse transazioni Conflitto Motivo read read No Perché l effetto di due operazioni read non dipende dall ordine di esecuzione read write Sì Perché l effetto di una read e una write dipende dall ordine di esecuzione write write Sì Perché l effetto di due operazioni write dipende dall ordine di esecuzione C12.14 7
Equivalenza seriale e conflitti Due transazioni sono equivalenti serialmente tutte le coppie di operazioni in conflitto sono eseguite nello stesso ordine su tutti gli oggetti che riferiscono Equivalenza seriale: regola per definire protocolli di controllo della concorrenza fra transazioni. Tali meccanismi gestiscono l interazione e i conflitti fra transazioni sullo stesso insieme di dati. Lock (m.e.) più usato metodi Ottimistico (assenza di conflitti) Timestamp - ordinamento - scarta (abort) transazioni non ordinate C12.15 Interleaving di operazioni di transazioni T e U non equivalenti serialmente Transazione T: Transazione U : x = read(i) write(i, 10) y = read(j) write(j, 30) write(j, 20) z = read (i) Le coppie di operazioni in conflitto non accedono nello stesso ordine ai due oggetti i e j C12.16 8
Problemi dovuti ad esecuzioni senza successo (abort) L esecuzione di un insieme di transazioni anche serialmente equivalenti non è esente dal problema delle dirty reads (letture non corrette) causate da esecuzioni senza successo di transazioni (abort) T modifica oggetto legge commit U abort Soluzione: ritardare il commit di U C12.17 Esempio: lettura errata quando la transazione T termina senza successo Transazione T: a.getbalance() a.setbalance(balance + 10) balance = a.getbalance() $100 a.setbalance(balance + 10) $110 abort transaction Transazione U: a.getbalance() a.setbalance(balance + 20) balance = a.getbalance() $110 a.setbalance(balance + 20) $130 commit transaction U ha letto un valore che è stato poi annullato da abort di T C12.18 9
Problemi dovuti a ripetizione L esecuzione senza successo di una transazione (abort) ne può causare altre (effetto cascata) Si evita imponendo che la read di oggetti avvenga solo se le precedenti write su quell oggetto sono state eseguite da transazioni completate (commit) Si ritarda l esecuzione della read Condizione necessaria per la possibilità di recuperare lo stato precedente (annullabilità di operazioni) premature writes interazione fra operazioni write sullo stesso oggetto eseguite da diverse transazioni (soggette ad abort) -> ripristinare lo stato precedente (storia delle modifiche) uso di before images per tutte le write di ogni transazione per garantire correttezza: si ritarda l esecuzione della write finchè non ha completato (commit o abort) la transazione che ha aggiornato l oggetto subito prima C12.19 Riscrittura su valori non definitivi Transazione T: a.setbalance(105) $100 a.setbalance(105) $105 Transazione U: a.setbalance(110) a.setbalance(110) $110 Se U abort e T commit il valore deve essere... C12.20 10
Realizzazione Esecuzione stretta di transazioni: Si ritarda l esecuzione della read e della write per risolvere entrambi i problemi delle dirty reads e delle premature writes -> garantisce la proprietà di isolamento Per gestire il problema del recupero dello stato a seguito di abort si mantengono versioni intermedie e parziali e si memorizza la versione definitiva in modo permanente solo al tempo della commit C12.21 Transazioni annidate T : transazione top-level T 1 = opensubtransaction T 2 = opensubtransaction T 1 : T 2 : opensubtransaction opensubtransaction prov. commit T 11 : T 12 : T 21: prov. commit prov. commit commit opensubtransaction abort opensubtransaction prov. commit T 211 : Esecuzione concorrente per T allo stesso livello Controllo dell accesso a risorse condivise (serializzazione) commit temporanei delle sottotransazioni prov.commit Vantaggi: prestazioni, tolleranza ai guasti (abort) di sottotransazioni distribuzione e scalabilità C12.22 11
Controllo della concorrenza: lock Accesso in mutua esclusione agli oggetti che vengono modificati Possibile stallo Granularità: minima informazione da serializzare Molto applicato Algoritmo two-phase locking I fase II fase crescita aggiornamento acquisizione lock rilascio lock t C12.23 Transazioni T e U con locks esclusivi Transazione T: balance = b.getbalance() b.setbalance(bal*1.1) a.withdraw(bal/10) Transazione U: balance = b.getbalance() b.setbalance(bal*1.1) c.withdraw(bal/10) Operazioni Locks Operazioni Locks opentransaction bal = b.getbalance() lock B b.setbalance(bal*1.1) opentransaction a.withdraw(bal/10) lock A bal = b.getbalance() waits for T s lock on B closetransaction unlock A, B lock B b.setbalance(bal*1.1) c.withdraw(bal/10) lock C closetransaction unlock B, C C12.24 12
Compatibilità di Lock Schema molti lettori-uno scrittore read e write lock Per un oggetto Lock richiesto read write Lock già assegnato nessuno OK OK read OK wait write wait wait C12.25 Uso di locks nel two-phase locking stretto 1. Quando una operazione accede ad un oggetto in una transazione: (a) Se l oggetto non è già locked, si esegue il lock e l operazione continua (b) Se l oggetto ha un lock in conflitto con un altra transazione, la transazione deve aspettare fino alla unlock. (c) Se l oggetto ha un lock senza conflitto con un altra transazione, il lock è condiviso e l operazione continua (d) Se l oggetto ha già un lock nella stessa transazione, il lock è promosso se necessario e l operazione continua (per lock in conflitto si applica la regola (b)) 2. Quando una transazione è completata (commit o abort), il servente blocca (unlocks) tutti gli oggetti bloccati per la transazione C12.26 13
classe Lock public class Lock { private Object object; // l oggetto protetto dal lock private Vector holders; // identificatore TIDs della transazione corrente che ha il lock private LockType locktype; // tipo corrente public synchronized void acquire(transid trans, LockType alocktype ){ while(/*un altra transazione ha il lock nel modo di conflitto*/) { try { wait(); }catch ( InterruptedException e) } if(holders.isempty()) { // nessun TIDs ha il lock holders.addelement(trans); locktype = alocktype; } else if(/*un altra transazione ha il lock, va condiviso*/ ) ){ if(/* questa transazione non è un holder*/) holders.addelement(trans); } else if (/* questa transazione è un holder ma vuole lock esclusivo */) locktype.promote(); } C12.27 } Continua continua public synchronized void release(transid trans ){ holders.removeelement(trans); // pone locktype a nessuno notifyall(); } } // rimuove questo holder C12.28 14
Classe LockManager public class LockManager { private Hashtable thelocks; } public void setlock(object object, TransID trans, LockType locktype){ Lock foundlock; synchronized(this){ // trova il lock associato all oggetto // se non c è lo crea e lo aggiunge alla hashtable } foundlock.acquire(trans, locktype); } // sincronizza questo perché si vogliono eliminare tutte le entries public synchronized void unlock(transid trans) { Enumeration e = thelocks.elements(); while(e.hasmoreelements()){ Lock alock = (Lock)(e.nextElement()); if(/* trans è un holder di questo lock*/ ) alock.release(trans); } } C12.29 Locking e annidamento Per le transazioni annidate occorre che - ogni insieme di T annidate non deve vedere risultati intermedi di altri insiemi di T annidate - ogni T nell insieme delle annidate non deve vedere risultati intermedi delle altre T nell insieme stesso ereditarietà del padre del lock acquisito da una sottot al completamento al livello più alto si ereditano tutti i lock acquisiti nel sottoalbero di annidamento si evitano in tal modo le visioni parziali non completate Il figlio non viene eseguito concorrentemente al padre, ma eredita il lock necessario temporaneamente Figli allo stesso livello sono concorrenti e competono serializzando il lock 1. una sottot acquisisce un read lock se nessuna T attiva ha write lock e chi ha wl è un suo antenato 2. una sottot acquisisce un write lock se nessuna T attiva ha read o write lock e chi ha rl o wl è un suo antenato 3. quando la sottot commit i lock sono ereditati dal padre nello stesso tipo 4. quando la sottot abort i lock sono persi, se il padre ne ha, li tiene C12.30 15
Stallo con write locks Transazione T Transazione U Operazione Locks Operazione Locks a.deposit(100); write lock A b.deposit(200) write lock B b.withdraw(100) waits for U s a.withdraw(200); waits for T s lock on B lock on A Stallo: quando i membri di un insieme di transazioni aspetta il rilascio di lock da parte di altri membri Dipendenza indiretta sugli oggetti C12.31 Grafo di attesa circolare assegnato a attesa A T U T U attesa B assegnato a C12.32 16
Ciclo in un grafo di wait-for U T V Abort -> C12.33 Esempio di grafo con wait-for V Assegnato a T W T U W Assegnato a C Assegnato a V U Assegnato a B attesa rl wl più cicli C12.34 17
Risoluzione dello stallo nell esempio:uso di timeout Transazione T Transazione U Operazioni Locks Operazioni Locks a.deposit(100); b.withdraw(100) write lock A lock su B (timeout elapses) T s lock su A diventa vulnerabile unlock A, abort T b.deposit(200) write lock B waits for U s a.withdraw(200); waits for T s a.withdraw(200); lock su A write locks A unlock A, B C12.35 Compatibilità di Lock (locks read, write e commit) Locking basato su due versioni: variante del two-phase locking per aumentare la concorrenza Ritarda il lock esclusivo finché la transazione non completa con commit Metodo ottimistico - tre tipi di lock: read, write, commit Per un oggetto Lock da imporre read write commit Lock già imposti nessuno OK OK OK read OK OK wait write OK wait commit wait wait C12.36 18
Gerarchia di lock: esempio Lock gerarchico: variante del two-phase locking per aumentare la concorrenza Lock di diversa granularità per ridurre l overhaed di esecuzione delle transazioni e ridurre il numero di lock Branch A B C Account I lock del padre hanno lo stesso effetto di quello dei figli Si riducono i lock C12.37 Gerarchia di lock per una agenda Settimana Lunedì Martedì Mercoledì Giovedì Venerdì ore 9:00 10:00 10:00 11:0011:00 12:0012:00 13:0013:00 14:0014:00 15:0015:00 16:00 C12.38 19
Tabella di compatibilità di lock per lock gerarchici Ogni nodo della gerarchia può essere soggetto a lock Il lock sul padre Per un oggetto Lock da imporre read write I-read I-write Lock già imposti nessuno OK OK OK OK Intention-lock -> implicito lock sui figli read OK wait OK wait write wait wait wait wait I-read OK wait OK OK I-write wait wait OK OK Prima di ottenere un lock sul figli si deve ottenere un intention lock sugli antenati (padre) C12.39 Controllo della concorrenza: ottimistico Assume - ottimisticamente - che non esistano conflitti fra le operazioni Controlla a tempo di commit se vi sono state interferenze e in tal caso annulla le transazioni Senza stallo Massimo livello di concorrenza Svantaggio: sotto ipotesi di carico pesante la probabilità di interferenza e conflitto è molto elevata - possibile starvation Fase di lavoro Fase di convalida Fase di aggiornamento - versioni parziali (tentativo) - controllo alla chiusura - versioni da temporanee a permanenti C12.40 20
Serializzabilità della transazione T 1 rispetto alla transazione T 2 Transazioni numerate in ordine crescente nella fase di convalida Regole da verificare nella fase di convalida Le transazioni sovrapposte nel tempo sono serializzabili? T 1 T 2 Regola write read 1. T 2 non deve leggere oggetti scritti da T 1 read write 2. T 1 non deve leggere oggetti scritti da T 2 write write 3. T 2 non deve scrivere oggetti scritti da T 1 e T 1 non deve scrivere oggetti scritti da T 2 Le convalida viene eseguita come sezione critica Se la fase di aggiornamento è esclusiva, la regola 3 è sempre verificata Non si possono avere dirty read C12.41 Convalida della transazione T 1 Lavoro T 2 Convalida Aggiornamento Transazioni completate prima Transazione da validare T 3 T v Transazioni attive dopo attiva 1 attiva 2 Convalida backward forward C12.42 21
Convalida di transazioni Convalida backward della transazione T v boolean valid = true; for (int T i = starttn+1; T i <= finishtn; T i ++){ if (read set di T v interseca write set di T i ) valid = false; } Convalida forward della transazione T v boolean valid = true; for (int T id = active1; T id <= activen; T id ++){ if (write set di T v interseca read set of T id ) valid = false; } Ritarda Abort T v Abort T v Abort active I starttn max # di transazione assegnato quando T v inizia la fase lavoro finishtn max # di transazione assegnato quando T v inizia la fase convalida C12.43 Controllo della concorrenza: timestamp e ordinamento Ad ogni transazione è associato un timestamp (etichetta unica) Ogni file (oggetto) ha un timestamp read e timestamp write che registra il tempo dell ultima transazione che ha avuto accesso (unica copia) Il file (oggetto) autorizza l operazione (read o write) solo a transazioni con timestamp maggiore (più recente) del timestamp del file (accesso di una transazione per volta) Le transazioni che arrivano in ritardo -> abort Verifica immediata della validità Senza stallo C12.44 22
Conflitti di operazione per ordine dei timestamp Regola T c T i 1. write read T c non deve eseguire una write su un oggetto su cui un T i >T c ha eseguito una read ciò richiede T c max read timestamp dell oggetto 2. write write T c non deve eseguire una write su un oggetto su cui un T i >T c ha eseguito una write ciò richiede T c > write timestamp dell oggetto committed 3. read write T c non deve eseguire una read su un oggetto su cui un T i >T c ha eseguito una write ciò richede T c > write timestamp dell oggetto committed C12.45 Operazioni write e timestamps (a) T 3 write (b) T 3 write Prima T 2 Prima T 1 T 2 Key: T i Dopo T 2 T 3 Dopo T 1 T 2 T 3 Committed Tempo Tempo T i Tentative (c) T 3 write Prima T 1 T 4 (d) T 3 Prima write T 4 Transaction aborts Oggetto prodotto dalla transazione T i (con write timestamp T i ) T 1 <T 2 <T 3 <T 4 Dopo T 1 T 3 T 4 Dopo T 4 Tempo Tempo (a), (b), (c) T 3 read timestamp T 3 < write timestamp (committed obj) C12.46 23
Regola di ordinamento di write con timestamp if (T c max read timestamp su D && T c > write timestamp sulla versione completata di D) esegue la write sulla versione tentativo di D con write timestamp T c else /* write è troppo in ritardo */ Abort transazione T c Per decidere se accettare una write di T c sull oggetto D C12.47 Regola di ordinamento di read con timestamp if ( T c > write timestamp sulla versione committed di D) { sia D selected la versione di D con il max write timestamp T c if (D selected è committed) esegui read sulla versione D selected else Wait until la transazione che ha creato la versione D selected commits o aborts then riapplica la regola read } else Abort transazione T c Per decidere se accettare una read di T c sull oggetto D C12.48 24
Esempio (a) T 3 read (a) T 3 read Key: T 2 read continua T 2 T 4 read continua T i Selected Time Selected Time Committed (a) T 3 read T 1 T 2 read aspetta Selected Time (a) T 3 read T 4 Transaction aborts Time T i Tentative Oggetto prodotto dalla transazione T i (con write timestamp T i ) T 1 < T 2 < T 3 < T 4 versione selezionata con write timestamp T 3 C12.49 Timestamps nelle transazioni T e U Timestamps e versioni di oggetti T U A B C RTS WTS RTS WTS RTS WTS {} S {} S {} S opentransaction bal = b.getbalance() {T} b.setbalance(bal*1.1) opentransaction bal = b.getbalance() wait for T a.withdraw(bal/10) commit S, T T T bal = b.getbalance() {U} b.setbalance(bal*1.1) T, U c.withdraw(bal/10) S, T S, U C12.50 25
Operazione write in ritardo che rende la read non valida T 3 read; T 3 write; T 5 read; T 4 write; T 2 T T 3 1 T 3 T 5 Time T 1 < T 2 < T 3 < T 4 < T 5 Key: T i Ti Oggetto prodotto dalla transazione T i T k T k (con write timestamp T i e read timestamp T k ) Committed Tentative C12.51 26