770 likes | 883 Vues
Gegevensbanken 2012 T ransactieverwerking II: technieken voor concurrentiecontrole Bettina Berendt http://people.cs.kuleuven.be/~bettina.berendt/. Concurrentiecontrole en herstel : Motivatie & Samenvatting. Waar zijn we?. Les # wie wat 1 ED intro, ER
E N D
Gegevensbanken 2012Transactieverwerking II:technieken voor concurrentiecontrole Bettina Berendthttp://people.cs.kuleuven.be/~bettina.berendt/
Waar zijn we? Les # wie wat 1 ED intro, ER 2 ED EER, (E)ER naar relationeel schema 2 ED relationeel model 3 KV Relationele algebra & relationeel calculus 4,5 KV SQL 6 KV Programma's verbinden met gegevensbanken 7 KV Functionele afhankelijkheden & normalisatie 8 KV PHP 9 BB Beveiliging van gegevensbanken 10 BB Geheugen en bestandsorganisatie 11 BB Hashing 12 BB Indexstructuren 13 BB Queryverwerking 14-16 BB Transactieverwerking en concurrentiecontrole 17 BB Data mining en data warehousing 18 ED XML, NoSQL Fysisch model / vragen
Concurrentiecontrole Nog een plaats! Wacht even reserveer! U heeft hem Sorry ... t
Herhaling: Gewenste eigenschappen van transacties • Atomicity: ondeelbaarheid • transactie wordt volledig uitgevoerd, of helemaal niet • Consistency preservation: • consistente gegevensbank moet na transactie nog steeds consistent zijn • Isolation: geïsoleerdheid • effect van transactie moet zijn alsof het de enige transactie is die uitgevoerd werd (geen interferentie met andere transacties) • meerdere isolatieniveaus (bv. de 4 uit de ISO/ANSI standaard) • Durability: duurzaamheid • effect van transactie moet persistent zijn, mag niet verloren gaan concurrentie-controle
Herhaling: Testen of garanderen van serialiseerbarheid • Problemen met testen van serialiseerbaarheid: • interleaving van operaties wordt bepaald door het besturingssysteem, niet vooraf te voorspellen • transacties worden continu aangeboden • begin en einde van roosters moeilijk te voorspellen • Indien rooster niet serialiseerbaar blijkt: • herstel nodig duur • om deze problemen te vermijden: • test niet op serialiseerbaarheid • gebruik bij opstellen van transacties regels (protocols) om serialiseerbaarheid te verzekeren
Agenda Vergrendeling (locking) Tijdstempels Multiversietechnieken Optimistische concurrentiecontrole Granulariteit van items
Agenda Vergrendeling (locking) Tijdstempels Multiversietechnieken Optimistische concurrentiecontrole Granulariteit van items
Herhaling: Nog een voorbeeld (1) van les 14 OF niet-serialiseerbarheid ?↔? verloren aanpassingen
→ Doel • Met een eenvoudiger voorbeeld begrijpen waarom dit fouten kan veroorzaken (“Voorbeeld A“) • Zien hoe grendels en tijdstempels ermee omgaan • Met een licht veranderde versie van Voorbeeld A tonen • Dat er gelijkaardige roosters zijn die toch “aanvaardbaar” zijn: • Niet conflict-serialiseerbaar maar view-serialiseerbaar • En een system van regels om deze equivalentie te creëeren/vinden • „multiversie-concurrentiecontrole“
Voorbeeld A (1) T1 T2 r(Y) r(X) r(Y) Y := X + Y w(Y) r(X) X := X + Y w(X)
Voorbeeld A (1) Initial values: X = 20, Y = 30 Result of serial schedule [T1,T2]: X = , Y = Result of serial schedule [T2,T1]: X =, Y = T1 T2 r(Y) r(X) r(Y) Y := X + Y w(Y) r(X) X := X + Y w(X)
Voorbeeld A (1) Initial values: X = 20, Y = 30 Result of serial schedule [T1,T2]: X = 50, Y = 80 Result of serial schedule [T2,T1]: X = 70, Y = 50 T1 T2 r(Y) r(X) r(Y) Y := X + Y w(Y) r(X) X := X + Y w(X) Resultaat van dit rooster? X = ; Y = Is er een verloren aanpassing? Is dat conflict-serialiseerbar?
Vergrendeling • grendel (slot, lock) • variabele horend bij een gegevenselement in de gegevensbank • beschrijft de status van dat element t.o.v. mogelijke bewerkingen die erop kunnen worden uitgevoerd • soorten grendels: • binaire grendels: • twee mogelijke toestanden • gedeelde / exclusieve grendels (of read / write locks) • drie mogelijke toestanden
Binaire grendels • twee mogelijke toestanden: lock(X) = 1 of 0 • 1: X is niet toegankelijk • 0: X is toegankelijk • twee bewerkingen • lock_item(X): een transactie vraagt toegang tot X • unlock_item(X): een transactie geeft X weer vrij (deze bewerkingen zijn steeds atomair)
Binaire grendels: lock en unlock • lock manager van DBMS houdt • status van grendels, • wachtende transacties etc. bij lock_item(X): B: als LOCK(X) = 0 dan LOCK(X) := 1 anders wacht tot LOCK(X) = 0; spring naar B unlock_item(X): LOCK(X) := 0; als er transacties aan het wachten zijn op X: dan maak één van die transacties wakker
Regels voor vergrendeling:Elke transactie T moet volgende regels volgen 1. T moet lock_item(X) uitvoeren voor read_item(X) of write_item(X) 2. T moet unlock_item(X) uitvoeren nadat alle read_item(X) en write_item(X) van T zijn uitgevoerd 3. T mag geen lock_item(X) uitvoeren als het al een grendel op X heeft 4. T mag geen unlock_item(X) uitvoeren als het geen grendel op X heeft
Lees- / schrijf-vergrendeling • twee soorten grendels: lees-grendels en schrijf-grendels • ook gedeelde / exclusieve grendels genoemd • drie toestanden voor gegevenselement: • niet vergrendeld (geen grendel) • lees-grendel • schrijf-grendel • drie bewerkingen: • read_lock(X) • write_lock(X) • unlock_item(X)
read_lock(X): B: als LOCK(X)="unlocked" dan LOCK(X):="read-locked"; aantal_reads(X) := 1 anders als LOCK(X) = "read-locked" dan aantal_reads(X) := aantal_reads(X)+1 anders wacht tot LOCK(X)="unlocked"; spring naar B write_lock(X): B: als LOCK(X)="unlocked" dan LOCK(X) := "write-locked" anders wacht tot LOCK(X)="unlocked"; spring naar B
unlock_item(X): B: als LOCK(X)="write-locked" dan LOCK(X):="unlocked"; als er transacties zijn die wachten op X: dan maak 1 ervan wakker anders als LOCK(X) = "read-locked" dan aantal_reads(X) := aantal_reads(X)-1; als aantal_reads(X) = 0 dan LOCK(X) := "unlocked" als er transacties wachten op X: dan maak 1 ervan wakker
Regels voor vergrendeling (bij lees / schrijf-vergrendeling):Elke transactie T moet volgende regels volgen: 1. T moet read_lock(X) of write_lock(X) uitvoeren vóór eender welke read_item(X) 2. T moet write_lock(X) uitvoeren vóór write_item(X) 3. T moet unlock(X) uitvoeren nadat alle read_item(X) en write_item(X) uitgevoerd zijn 4. T mag geen read_lock(X) uitvoeren als het al een (lees- of schrijf-) grendel heeft op X (*) 5. T mag geen write_lock(X) uitvoeren als het al een (lees- of schrijf-) grendel heeft op X (*) 6. T mag geen unlock(X) uitvoeren als het geen grendel heeft op X
Afzwakken van regels • (*) regels kunnen afgezwakt worden: • upgrade: • als T al een leesgrendel op X heeft, en het is de enige transactie met een leesgrendel op X, dan kan dit met write_lock(X) in een schrijfgrendel veranderd worden • downgrade: • als T een schrijfgrendel op X heeft, kan dat met read_lock(X) verlaagd worden tot een leesgrendel = conversie van grendels
Initial values: X = 20, Y = 30 Result of serial schedule [T1,T2]: X = 50, Y = 80 Result of serial schedule [T2,T1]: X = 70, Y = 50 Lees-/schrijf-vergrendeling --> serialiseerbarheid? Voorbeeld A (2)
Lees-/schrijf-vergrendeling serialiseerbarheid? • Gebruik van bovenstaande regels vermijdt bepaalde problemen maar garandeert geen serialiseerbaarheid • vb: fig. 21.3 (vorige slide) • twee mogelijke seriële uitvoeringen: • 1. tel X bij Y op, tel dan Y bij X op • 2. tel Y bij X op, tel dan X bij Y op • in een serieel schema zal één van de transacties de originele X/Y gebruiken en de andere de aangepaste • in 21.3c gebruiken beide transacties de originele X/Y • probleem: Y is te vroeg vrijgegeven • daarom: strengere set regels (= een protocol) volgen
Twee-fasen-vergrendeling • protocol van vergrendeling om bepaalde problemen te vermijden: • alle vergrendelingen van een transactie gebeuren vóór de eerste ontgrendelbewerking • binnen een transactie gebeurt vergrendeling steeds in twee fasen: • "expanding phase": plaatsen van grendels • "shrinking phase": vrijgeven van grendels • de fasen zijn strikt gescheiden • eens een grendel vrijgegeven is, kunnen er geen nieuwe meer geplaatst worden • twee-fasen-vergrendeling garandeert serialiseerbaarheid • maar vermijdt geen deadlock / starvation
Voorbeeld A (3) origineel Met twee-fasen-vergrendeling
Voorbeeld A (3): maar ... Met twee-fasen-vergrendeling write_lock(X): B: als LOCK(X)="unlocked" dan LOCK(X) := "write-locked" anders wacht tot LOCK(X)="unlocked"; spring naar B
Deadlock • 2 processen wachten op elkaar • hebben elk een grendel die de ander wil • geven die grendel niet vrij voor ze de andere grendel krijgen
Varianten van twee-fasen-vergrendeling • basisversie: • zoals gezien • conservatieve 2FV: • alle grendels plaatsen voor transactie begint • vermijdt deadlocks • probleem: • niet altijd bekend op voorhand welke grendels nodig zullen zijn • strikte, resp. rigoureuze 2FV: • geen enkel schrijfgrendel, resp. grendel vrijgeven voor commit of abort • garandeert een strikt rooster • is niet deadlock-vrij
besluit: • twee-fasen-vergrendeling • garandeert serialiseerbaarheid van rooster • maar vermijdt geen deadlocks of starvation • om dit op te lossen nog andere technieken nodig • twee benaderingen van deadlock: • vermijden (deadlock prevention) • opsporen (deadlock detection)
Deadlock-vermijdende protocollen • alles vooraf vergrendelen (cf. conservatieve 2FV) • grote beperking op concurrentie • items steeds in welbepaalde volgorde vergrendelen • programmeur moet deze volgorde kennen: in de praktijk niet wenselijk • gebruik van tijdstempels (timestamps)
Agenda Vergrendeling (locking) Tijdstempels Multiversietechnieken Optimistische concurrentiecontrole Granulariteit van items
Deadlock-preventie met grendels en tijdstempels • elke transactie T krijgt tijdstempel TS(T) toegekend • als T1 start voor T2: TS(T1) < TS(T2) • mogelijke schema’s: • stel: • Ti wil X vergrendelen maar kan niet omdat Tj er een grendel op heeft • wait-die schema : • als TS(Ti) < TS(Tj) (Ti is ouder dan Tj ) • dan mag Ti wachten tot grendel vrijkomt • anders wordt Ti afgebroken (= de jongere transactie) en later herstart met dezelfde timestamp • wound-wait schema : • als TS(Ti) < TS(Tj) (Ti is ouder dan Tj ) • dan wordt Tj (de jongere transactie) afgebroken • anders mag Ti (de jongere transactie) wachten tot grendel vrijkomt
Vordelen en nadelen • in beide gevallen wordt jongste transactie afgebroken en later herstart • gemiddeld gaat minder werk verloren • voordeel: deadlock-vrij • oudere transactie wacht steeds op jongere (wait-die) of omgekeerd (wound-wait) • dus nooit lussen in wachtpatroon • nadeel: • sommige transacties worden afgebroken zelfs al zouden ze geen deadlock veroorzaken • wait-die : Ti mogelijk vaak afgebroken en herstart
Deadlock-preventie zonder tijdstempels • verschillende schema’s • niet wachten: "no waiting" schema • als een transactie een grendel niet kan krijgen, wordt ze direct afgebroken en na een zekere tijd herstart • voorzichtig wachten: "cautious waiting" schema • transactie mag alleen wachten op een grendel als de transactie die die grendel heeft niet zelf aan het wachten is • Stel: Ti wil X vergrendelen, Tj heeft grendel op X • als Tj niet zelf wacht op een grendel • dan laat Ti wachten • anders breek Ti af • is deadlock vrij! • gebruik van timeouts: • als een transactie langer wacht dan een welbepaalde tijd, wordt ze automatisch afgebroken en herstart • detecteert niet echt deadlocks
Deadlock-detectie • periodieke controle of systeem in deadlock is • enkel interessant wanneer er weinig interferentie tussen transacties is • (korte transacties die slechts weinig items vergrendelen, of weinig transacties) • detectie: op basis van "wacht op"-graaf • lus in graaf = deadlock • indien deadlock: • kies slachtoffer om af te breken • "victim selection": • voorkeur voor jonge transacties die weinig aanpassingen gemaakt hebben • of transacties die in meerdere cycles in de graaf betrokken zijn
Maar ... Begin T2 ... Deadlock → T2 is te jong → afbreken! T1 t
Maar ... Begin T2 ... Deadlock → T2 is te jong → afbreken! T1 t Begin T2 ... Deadlock → T2 is te jong → afbreken!
Maar ... Begin T2 ... Deadlock → T2 is te jong → afbreken! T1 t Begin T2 ... Deadlock → T2 is te jong → afbreken! Begin T2 ... Deadlock → T2 is te jong → afbreken!
Maar ... Begin T2 ... Deadlock → T2 is te jong → afbreken! T1 t Begin T2 ... Deadlock → T2 is te jong → afbreken! ... Begin T2 ... Deadlock → T2 is te jong → afbreken!
Starvation (“verhongeren”) • definitie: • een transactie moet steeds maar blijven wachten, terwijl andere transacties vooruitgaan 1. doordat andere wachtende transacties steeds de vrijkomende grendels krijgen, of 2. doordat de "victim selection" steeds deze transactie kiest • oplossingen: • 1: te vermijden door eerlijke toekenning van grendels • bv. first come, first serve • verschillende prioriteiten + proces dat lang wacht krijgt steeds hogere prioriteit • 2: te vermijden door eerlijke slachtofferselectie • selecteer transactie met laagste prioriteit • bij heropstarten van die transactie krijgt ze automatisch een hogere prioriteit • opmerking: • wait-die en wound-wait voorkomen starvation
Concurrentiecontrole d.m.v. Tijdstempels (zonder grendels) • serialiseerbaarheid garanderen d.m.v. tijdstempels i.p.v. grendels en deadlock-preventie/detectie • geen grendels nodig geen deadlocks mogelijk • er is één tijdstempel per transactie • tijdstempels zijn uniek • en in chronologische volgorde • T1 voor T2 aangeboden TS(T1) < TS(T2) • tijdstempels ordenen de transacties • het transactierooster met tijdstempelordening is equivalent met het serieel rooster met precies die volgorde van transacties
met elk item X worden twee tijdstempelwaarden geassocieerd: • read_TS(X) • grootste tiidstempel van alle transacties die met succes X gelezen hebben ( jongste transactie) • write_TS(X) • grootste tijdstempel van alle transacties die met succes X geschreven hebben ( jongste transactie) • voor een transactie T die read_item(X) of write_item(X) wil uitvoeren: • vergelijk tijdstempels • beslis of T die actie mag uitvoeren • vb: T mag X niet lezen als X door een transactie met latere tijdstempel geschreven is
wat als tijdstempels niet kloppen? • transactie afbreken, ongedaan maken, en opnieuw aanbieden (nu met latere TS) • bij ongedaan maken (rollback): • transacties die iets gelezen hebben dat door deze transactie geschreven werd ook ongedaan maken • cascading rollback • ordening op basis van tijdstempels • garandeert serialiseerbaarheid • maar niet elk serialiseerbaar rooster wordt aanvaard • vermijdt deadlock (maar geen starvation)
Basis tijdstempelordeningsalgoritme Transactie T voert write_item(X) uit: als read_TS(X) > TS(T) of write_TS(X) > TS(T): (write_item komt te laat, jongere transacties hebben intussen al een oudere waarde van X gelezen of een jongere geschreven) breek T af en maak T ongedaan anders write_item(X); write_TS(X) := TS(T) Transactie T voert read_item(X) uit: als write_TS(X) > TS(T): (te lezen waarde is intussen al overschreven door jongere transactie) breek T af en maak T ongedaan anders read_item(X); read_TS(X) := max(TS(T), read_TS(X))
Taak • Hoe verwerkt het tijdstempelordeningsalgoritme Voorbeeld A?
Voorbeeld A Voor rooster: r_TS(X) = w_TS(X) = r_TS(Y) = w_TS(Y) = 0 T1 T2 r(Y) r(X) r(Y) Y := X + Y w(Y) r(X) X := X + Y w(X) • T1 begint → TS(T1) = 1 • T1.r(Y) gewenst → w_TS(Y0) > TS(1)? neen → r_TS(Y) = max(1,0)=1 • T2 begint → TS(T2) = 3 • T2.r(X) gewenst → w_TS(X) > TS(T2)? neen → r_TS(X) =max(3,0) = 3 • T2.r(Y) gewenst → w_TS(Y) > TS(T2)? neen → r_TS(Y) = max(3,1) = 3 • T2.w(Y) gewenst → r_TS(Y) of w_TS(Y) > TS(T2)? Neen → w_TS(Y) = 3 • T1.r(X) gewenst → w_TS(X) > TS(T1)? neen → r_TS(X) = max(1,3) = 3 • T1.w(X) gewenst → r_TS(X) of w_TS(X) > TS(T1)? ja → ABORT T1 ! * A niet conflict- serialiseerbar; [T2,T1] wordt afgedwongen
problemen met het basis tijdstempelordeningsalgoritme: • cascading rollbacks • niet herstelbaar • reeds gecommitte transacties moeten soms ook ongedaan gemaakt worden • strikte tijdstempelordening: • = een variante van het basis algoritme • een transactie T • die read_item(X) of write_item(X) doet met TS(T) > write_TS(X) • wacht met deze operatie tot de transactie met timestamp write_item(X) gecommit of afgebroken is • garandeert strikt rooster
Thomas’ schrijfregel: licht gewijzigde versie t.o.v. basis tijdstempelordeningsalgoritme • legt geen conflict-serialiseerbaarheid op • verwerpt minder write_items • wijziging aan write_item procedure: Transactie T voert write_item(X) uit: als read_TS(X) > TS(T): (write_item komt te laat) breek T af en maak T ongedaan anders als write_TS(X)>TS(T): (write_item is niet meer relevant) voer de write_item niet uit maar ga gewoon door (evt. problemen hierdoor veroorzaakt worden ontdekt door andere regels) anders write_item(X); write_TS(X) := TS(T)