Transacties en hun controlemechanismen

Transactie

Een transactie is een reeks bewerkingen op gegevens die een begin en een einde heeft.

Een transactie is de opeenvolgende uitvoering van lees- en schrijfbewerkingen. Het einde van een transactie kan bestaan ​​uit het opslaan van de wijzigingen (commit) of het annuleren van de wijzigingen (rollback). Met betrekking tot een database bestaat een transactie uit meerdere verzoeken die als één verzoek worden behandeld.

Transacties moeten voldoen aan ACID-eigenschappen

Atomiciteit. De transactie wordt volledig of helemaal niet voltooid.

Samenhang. Bij het voltooien van een transactie mogen de beperkingen die aan de gegevens worden opgelegd (bijvoorbeeld beperkingen in de database) niet worden overtreden. Consistentie houdt in dat het systeem van de ene correcte toestand naar de andere correcte toestand wordt overgebracht.

Isolatie. Parallel lopende transacties mogen elkaar niet beïnvloeden, bijvoorbeeld door gegevens te wijzigen die door een andere transactie worden gebruikt. Het resultaat van het uitvoeren van parallelle transacties moet hetzelfde zijn als wanneer de transacties opeenvolgend zouden worden uitgevoerd.

Duurzaamheid. Eenmaal vastgelegd, mogen veranderingen niet verloren gaan.

Transactielogboek

Het logboek slaat wijzigingen op die door transacties zijn aangebracht en zorgt voor atomiciteit en stabiliteit van gegevens in het geval van een systeemstoring

Het logbestand bevat de waarden die de gegevens hadden voordat en nadat deze door de transactie werden gewijzigd. Vooruitschrijvende logstrategie vereist het toevoegen van een logvermelding over eerdere waarden vóór de start, en over definitieve waarden nadat de transactie is voltooid. Bij een plotselinge stop van het systeem leest de database de log in omgekeerde volgorde en annuleert de wijzigingen die door transacties zijn aangebracht. Nadat een onderbroken transactie is aangetroffen, voert de database deze uit en brengt er wijzigingen in aan in het logboek. Omdat de database zich in de staat bevindt ten tijde van de fout, leest hij de loggegevens in voorwaartse volgorde en retourneert de wijzigingen die door transacties zijn aangebracht. Op deze manier blijft de stabiliteit van reeds uitgevoerde transacties en de atomiciteit van de onderbroken transactie behouden.

Het simpelweg opnieuw uitvoeren van mislukte transacties is niet voldoende voor herstel.

Voorbeeld. De gebruiker heeft $ 500 op zijn rekening en de gebruiker besluit dit op te nemen bij een geldautomaat. Er zijn twee transacties gaande. De eerste leest de saldowaarde en als er voldoende geld op de balans staat, geeft hij geld uit aan de gebruiker. De tweede trekt het vereiste bedrag van het saldo af. Laten we zeggen dat het systeem crashte en de eerste bewerking mislukte, maar de tweede wel. In dit geval kunnen we geen geld opnieuw uitgeven aan de gebruiker zonder het systeem terug te brengen naar de oorspronkelijke staat met een positief saldo.

Isolatieniveaus

Lees Toegewijd

Het Dirty Read-probleem is dat een transactie het tussenresultaat van een andere transactie kan lezen.

Voorbeeld. De initiële saldowaarde is $ 0. T1 voegt $ 50 toe aan uw saldo. T2 leest de saldowaarde ($50). T1 negeert de wijzigingen en sluit af. T2 gaat door met de uitvoering met onjuiste saldogegevens.

De oplossing is het lezen van vaste gegevens (Read Commited), waardoor het lezen van door de transactie gewijzigde gegevens niet mogelijk is. Als transactie A een bepaalde set gegevens heeft gewijzigd, wordt transactie B, wanneer hij toegang krijgt tot deze gegevens, gedwongen te wachten tot transactie A is voltooid.

Herhaalbaar lezen

Probleem met verloren updates. T1 slaat wijzigingen op bovenop de wijzigingen van T2.

Voorbeeld. De initiële saldowaarde is $ 0 en twee transacties vullen tegelijkertijd het saldo aan. T1 en T2 lezen een saldo van $0. T2 telt vervolgens €200 op bij €0 en slaat het resultaat op. T1 telt €100 op bij €0 en slaat het resultaat op. Het eindresultaat is $ 100 in plaats van $ 300.

Onherhaalbaar leesprobleem. Het lezen van dezelfde gegevens levert herhaaldelijk verschillende waarden op.

Voorbeeld. T1 leest een saldowaarde van $0. T2 voegt vervolgens $ 50 toe aan het saldo en eindigt. T1 leest de gegevens opnieuw en vindt een discrepantie met het vorige resultaat.

Herhaalbare lezing zorgt ervoor dat een tweede lezing hetzelfde resultaat oplevert. Gegevens die door één transactie worden gelezen, kunnen bij andere niet worden gewijzigd totdat de transactie is voltooid. Als transactie A een bepaalde set gegevens heeft gelezen, wordt transactie B, wanneer hij toegang krijgt tot deze gegevens, gedwongen te wachten tot transactie A is voltooid.

Geordende lezing (serialiseerbaar)

Phantom Reads-probleem. Twee query's die gegevens selecteren op basis van een bepaalde voorwaarde retourneren verschillende waarden.

Voorbeeld. T1 vraagt ​​om het aantal van alle gebruikers waarvan het saldo groter is dan $0 maar minder dan $100. T2 trekt $ 1 af van een gebruiker met een saldo van $ 101. T1 verzendt het verzoek opnieuw.

Geordende lezing (serialiseerbaar). Transacties worden volledig opeenvolgend uitgevoerd. Het is verboden om gegevens die binnen de voorwaarden van het verzoek vallen, bij te werken of toe te voegen. Als transactie A gegevens uit de hele tabel heeft opgevraagd, wordt de hele tabel bevroren voor andere transacties totdat transactie A is voltooid.

Planner

Stelt de volgorde in waarin bewerkingen moeten worden uitgevoerd tijdens parallelle transacties.

Biedt een bepaald isolatieniveau. Als het resultaat van bewerkingen niet afhankelijk is van hun volgorde, zijn dergelijke bewerkingen commutatief (permuteerbaar). Leesbewerkingen en bewerkingen op verschillende gegevens zijn commutatief. Lees-schrijf- en schrijf-schrijfbewerkingen zijn niet commutatief. De taak van de planner is het interleaven van bewerkingen die worden uitgevoerd door parallelle transacties, zodat het uitvoeringsresultaat gelijkwaardig is aan de sequentiële uitvoering van transacties.

Mechanismen voor het controleren van parallelle taken (Concurrency Control)

Optimistisch is gebaseerd op het opsporen en oplossen van conflicten, pessimistisch is gebaseerd op het voorkomen van conflicten.

In de optimistische benadering hebben meerdere gebruikers kopieën van de gegevens tot hun beschikking. De eerste persoon die het bewerken voltooit, slaat de wijzigingen op, terwijl de anderen de wijzigingen moeten samenvoegen. Een optimistisch algoritme laat conflicten toe, maar het systeem moet herstellen van het conflict.

Met een pessimistische benadering verhindert de eerste gebruiker die de gegevens vastlegt dat anderen de gegevens ontvangen. Als conflicten zeldzaam zijn, is het verstandig om voor de optimistische strategie te kiezen, omdat deze een hoger niveau van gelijktijdigheid biedt.

Vergrendelen

Als één transactie gegevens heeft vergrendeld, moeten andere transacties wachten totdat deze worden ontgrendeld wanneer ze toegang krijgen tot de gegevens.

Een blok kan over een database, tabel, rij of attribuut worden gelegd. Shared Lock kan door meerdere transacties aan dezelfde gegevens worden opgelegd, staat toe dat alle transacties (inclusief degene die deze heeft opgelegd) worden gelezen, verbiedt wijziging en exclusieve vastlegging. Exclusieve vergrendeling kan door slechts één transactie worden opgelegd, staat alle acties van de opleggende transactie toe en verbiedt alle acties van anderen.

Een impasse is een situatie waarin transacties in een hangende toestand terechtkomen die voor onbepaalde tijd duurt.

Voorbeeld. De eerste transactie wacht tot de gegevens die door de tweede zijn vastgelegd, worden vrijgegeven, terwijl de tweede wacht tot de gegevens die door de eerste zijn vastgelegd, worden vrijgegeven.

Een optimistische oplossing voor het impasseprobleem zorgt ervoor dat de impasse kan optreden, maar herstelt vervolgens het systeem door een van de transacties die bij de impasse betrokken waren, terug te draaien.

Met bepaalde tussenpozen wordt er gezocht naar impasses. Een van de detectiemethoden is op basis van tijd, dat wil zeggen dat er sprake is van een impasse als de transactie te lang duurt om te voltooien. Wanneer er een impasse wordt geconstateerd, wordt een van de transacties teruggedraaid, waardoor andere transacties die bij de impasse betrokken zijn, kunnen worden voltooid. De keuze van het slachtoffer kan gebaseerd zijn op de waarde van transacties of hun anciënniteit (Wait-Die- en Wound-wait-regelingen).

Elke transactie T er wordt een tijdstempel toegewezen TS met de starttijd van de transactie.

Wacht-sterf.

als TS(Ti) < TS(Tj)dan Ti wacht, anders Ti rolt terug en begint opnieuw met hetzelfde tijdstempel.

Als een jonge transactie een hulpbron heeft verworven en een oudere transactie om dezelfde hulpbron vraagt, mag de oudere transactie wachten. Als een oudere transactie een bron heeft verworven, wordt de jongere transactie waarin die bron wordt aangevraagd, teruggedraaid.

Wond-wacht.

als TS(Ti) < TS(Tj)dan Tj gaat terug en begint opnieuw met hetzelfde tijdstempel, anders Ti aan het wachten.

Als een jongere transactie een bron heeft verworven en een oudere transactie om dezelfde bron vraagt, wordt de jongere transactie teruggedraaid. Als een oudere transactie een hulpbron heeft verworven, mag de jongere transactie die om die hulpbron vraagt, wachten. Op prioriteit gebaseerde slachtofferselectie voorkomt impasses, maar draait transacties terug die niet in een impasse zitten. Het probleem is dat transacties vele malen kunnen worden teruggedraaid omdat... een oudere transactie kan de bron lange tijd vasthouden.

Een pessimistische oplossing voor het impasseprobleem staat niet toe dat een transactie wordt uitgevoerd als er een risico bestaat op een impasse.

Om een ​​impasse te detecteren, wordt een grafiek geconstrueerd (wachtgrafiek, wacht-op-grafiek), waarvan de hoekpunten transacties zijn, en de randen worden gericht van transacties die wachten op het vrijgeven van gegevens naar de transactie die deze gegevens heeft vastgelegd. Er wordt aangenomen dat er sprake is van een impasse als de grafiek een lus heeft. Het construeren van een wachtgrafiek is, vooral in gedistribueerde databases, een dure procedure.

Tweefasige vergrendeling - voorkomt impasses door alle bronnen die door een transactie worden gebruikt aan het begin van de transactie in beslag te nemen en deze aan het einde vrij te geven

Alle blokkeerhandelingen moeten voorafgaan aan de eerste ontgrendeling. Het heeft twee fasen: de groeifase, waarin de grepen zich ophopen, en de krimpfase, waarin de grepen worden losgelaten. Als het onmogelijk is om een ​​van de bronnen te veroveren, begint de transactie opnieuw. Het is mogelijk dat een transactie niet in staat is om de benodigde middelen te verkrijgen, bijvoorbeeld als meerdere transacties strijden om dezelfde middelen.

Een commit in twee fasen zorgt ervoor dat de commit wordt uitgevoerd op alle databasereplica's

Elke database voert informatie in over de gegevens die in het logboek worden gewijzigd en reageert op de coördinator OK (stemfase). Nadat iedereen OK heeft geantwoord, geeft de coördinator een signaal af dat iedereen verplicht zich te committeren. Na het committen reageren de servers OK; als tenminste één server niet OK reageert, stuurt de coördinator een signaal om de wijzigingen naar alle servers te annuleren (Voltooiingsfase).

Tijdstempelmethode

Een oudere transactie wordt teruggedraaid wanneer wordt geprobeerd toegang te krijgen tot gegevens die bij een jongere transactie betrokken zijn

Aan elke transactie wordt een tijdstempel toegewezen TS overeenkomend met de starttijd van uitvoering. Als Ti senior Tjdan TS(Ti) < TS(Tj).

Wanneer een transactie wordt teruggedraaid, krijgt deze een nieuwe tijdstempel toegewezen. Elk gegevensobject Q betrokken bij de transactie is gemarkeerd met twee labels. W-TS(Q) — tijdstempel van de jongste transactie die met succes een record heeft voltooid Q. R-TS(Q) — tijdstempel van de jongste transactie waarop een leesrecord is uitgevoerd Q.

Wanneer de transactie T verzoeken om gegevens te lezen Q Er zijn twee opties.

als TS(T) < W-TS(Q), dat wil zeggen dat de gegevens zijn bijgewerkt door een jongere transactie dan de transactie T rolt terug.

als TS(T) >= W-TS(Q), vervolgens wordt de meting uitgevoerd en R-TS(Q) is aan het worden MAX(R-TS(Q), TS(T)).

Wanneer de transactie T vraagt ​​gegevenswijzigingen aan Q Er zijn twee opties.

als TS(T) < R-TS(Q)Dat wil zeggen dat de gegevens al door een jongere transactie zijn gelezen en als er een wijziging wordt aangebracht, ontstaat er een conflict. Transactie T rolt terug.

als TS(T) < W-TS(Q), dat wil zeggen dat de transactie een nieuwere waarde probeert te overschrijven, wordt transactie T teruggedraaid. In andere gevallen wordt de wijziging uitgevoerd en W-TS(Q) wordt gelijk TS(T).

Er is geen dure wachtgrafiekconstructie vereist. Oudere transacties zijn afhankelijk van nieuwere, dus er zijn geen cycli in de wachtgrafiek. Er zijn geen impasses omdat transacties niet worden gewacht, maar onmiddellijk worden teruggedraaid. Cascading rollbacks zijn mogelijk. Als Ti rolde weg en Tj Ik heb de gegevens gelezen die ik heb gewijzigd Tidan Tj moet ook terugdraaien. Als tegelijkertijd Tj al is gepleegd, dan is er sprake van schending van het stabiliteitsbeginsel.

Een van de oplossingen voor trapsgewijze terugdraaiingen. Een transactie voltooit aan het eind alle schrijfbewerkingen en andere transacties moeten wachten tot die bewerking is voltooid. Transacties wachten totdat ze zijn vastgelegd voordat ze worden gelezen.

Thomas-schrijfregel - een variatie op de tijdstempelmethode waarbij gegevens die door een jongere transactie zijn bijgewerkt, niet mogen worden overschreven door een oudere transactie

Transactie T vraagt ​​gegevenswijzigingen aan Q. als TS(T) < W-TS(Q), dat wil zeggen dat de transactie een nieuwere waarde probeert te overschrijven, wordt transactie T niet teruggedraaid zoals bij de tijdstempelmethode.

Bron: www.habr.com

Voeg een reactie