2024-01-08 23:05:31 +01:00
|
|
|
# Transakce
|
|
|
|
|
|
|
|
## Transakční zpracování
|
|
|
|
|
|
|
|
**Ochrana integrity dat**
|
|
|
|
- stav databáze
|
|
|
|
- dán hodnotami objektů databáze v daném okamžiku
|
|
|
|
- objektem se rozumí
|
|
|
|
- tabulka, záznam, položka a spojení
|
|
|
|
|
|
|
|
**Konzistentní stav databáze**
|
|
|
|
- podmínky definující konzistentní stav databáze jsou definovány integritními omezeními
|
|
|
|
- jednoduché deklarativní formou
|
|
|
|
- složitější procedurální formou
|
|
|
|
|
|
|
|
**Porušení integrity DB**
|
|
|
|
- porušení integrity DB = porušení konzistentního stavu DB
|
|
|
|
- příčiny
|
|
|
|
- selhání technického/hw zařízení (disk)
|
|
|
|
- selhání operačního systému
|
|
|
|
- chyba v aplikačním programu
|
|
|
|
- chybný zásah obsluhy
|
|
|
|
- chybná data
|
|
|
|
- příčin porušení integrity je tolik, že je těžké jim zabránit
|
|
|
|
- SŘBD je tedy vybaven
|
|
|
|
- mechanismem detekce nekonzistentního stavu
|
|
|
|
- mechanismem zotavení
|
|
|
|
|
|
|
|
**Ochrana integrity**
|
|
|
|
- prostředky poskytnuté OS
|
|
|
|
- kopie souboru (zpravidla na různá média)
|
|
|
|
- kontrolní bod (záloha všech souborů a případné obnovení)
|
|
|
|
- speciálně vyvinuté pro databázové systémy
|
|
|
|
- transakce
|
|
|
|
|
|
|
|
**Transakce**
|
|
|
|
- posloupnost operací nad objekty databáze
|
|
|
|
- z pohledu uživatele ucelená operace
|
|
|
|
- je
|
|
|
|
- logickou jednotkou práce
|
|
|
|
- jednotkou zotavení z chyb
|
|
|
|
- po dobu provádění transakce není databáze v konzistentním stavu
|
|
|
|
- příklad: změna čísla čtenáře
|
|
|
|
- u čtenáře ale i všech jeho výpůjček
|
|
|
|
|
|
|
|
**Stavy transakce**
|
|
|
|
- aktivní (A)
|
|
|
|
- stav od začátku provádění
|
|
|
|
- chybný (F)
|
|
|
|
- v pokračování transakce nelze pokračovat
|
|
|
|
- částečně potvrzený (PC)
|
|
|
|
- po provedení poslední elementární operace
|
|
|
|
- transakce nebyla dosud potvrzena
|
|
|
|
- zrušený (AB)
|
|
|
|
- po příkazu `ROLLBACK`, vrácení do původního stavu
|
|
|
|
- potvrzený (C)
|
|
|
|
- úspěšné doknčení a potvrzení příkazem `COMMIT`
|
|
|
|
|
|
|
|
**Vlastnosti transakce**
|
|
|
|
- atomicita (**A**tomicity)
|
|
|
|
- buď všechny operace nebo žádná
|
|
|
|
- konzistence (**C**onsistency)
|
|
|
|
- DB v konzistentním stavu před i po transakci
|
|
|
|
- izolovanost (**I**solation)
|
|
|
|
- paralelně probíhající transakce se nijak neovlivňují
|
|
|
|
- trvalost (**D**urability)
|
|
|
|
- po úspěšném potvrzení transakce všechny změny v databázi nemohou být ztraceny (ani při havárii systému)
|
|
|
|
|
|
|
|
**Žurnál**
|
|
|
|
- základní nástroj pro ochranu transakcí
|
|
|
|
- znám též jako logovací protokol
|
|
|
|
- zapisují se do něj změny od posledního kontrolního bodu
|
|
|
|
- obecně obsahuje
|
|
|
|
- identifikaci transakce
|
|
|
|
- kdo změnu provádí
|
|
|
|
- kdy je změna provedena
|
|
|
|
- kterého objektu se týká
|
|
|
|
- novou hodnotu objektu
|
|
|
|
- někdy i starou/původní hodnotu objektu
|
|
|
|
|
|
|
|
**Metody používání žurnálu**
|
|
|
|
- dopředné procházení (`REDO`)
|
|
|
|
- po chybě se vychází z kopie uložené v kontrolním bodě
|
|
|
|
- postupně se provádí změny uložené v žurnálu až do chybového okamžiku
|
|
|
|
- potřebujeme jen nové hodnoty objektů
|
|
|
|
- zpětné použití žurnálu (`UNDO`, `ROLLBACK`)
|
|
|
|
- po chybě se vychází ze současného (nekonzistentního) stavu DB
|
|
|
|
- využíváme starých hodnot v žurnálu do začátku chybné transakce
|
|
|
|
- postupným zpětným odvíjením žurnálu se dojde k začátku chybné transakce
|
|
|
|
|
|
|
|
**Metody ochrany transakce**
|
|
|
|
- odložený zápis do databáze
|
|
|
|
- tvorba žurnálu s odloženými realizacemi změn
|
2024-01-16 13:43:12 +01:00
|
|
|
- v minulosti též **dvoufázové potvrzování**
|
2024-01-08 23:05:31 +01:00
|
|
|
- přímý zápis do databáze
|
|
|
|
- tvorba žurnálu s bezprostřední realizací změn
|
|
|
|
|
2024-01-16 13:43:12 +01:00
|
|
|
**Odložený zápis do databáze**
|
2024-01-08 23:05:31 +01:00
|
|
|
- transakce nesmí měnit hodnoty objektů v databázi dříve, než je částečně potvrzena
|
|
|
|
- transakce nemůže být částečně potvrzená, pokud není vytvořen příslušný záznam o změnách v žurnálu
|
|
|
|
- žurnál nevyžaduje staré hodnoty objektů
|
|
|
|
- nevýhoda: pomalé
|
|
|
|
+ pokud došlo k chybě
|
|
|
|
+ před uložením do žurnálu
|
|
|
|
+ přechod ze stavu _aktivní_ do _částečně porvrzený_
|
|
|
|
+ nedošlo ke změnám v databázi (zůstala v konzistentním stavu)
|
|
|
|
+ po částečném potvrzení transakce
|
|
|
|
+ přechod ze stavu _částečně potvrzený_ do stavu _potvrzený_
|
|
|
|
+ všechny změny jsou uloženy v žurnálu
|
|
|
|
+ na žurnál bude použita metoda `REDO`
|
|
|
|
|
|
|
|
**Strategie obnovení odloženého zápisu do DB**
|
|
|
|
|
|
|
|
- vytvoříme seznam `REDO`
|
|
|
|
- žurnál procházíme od kontrolního bodu do předu
|
|
|
|
- narazíme-li na konec transakce, vložíme ji do `REDO`
|
|
|
|
- transakce v seznamu `REDO` zpracujeme metodou `REDO`
|
|
|
|
- nedokončené transakce řešit nemusíme, protože neprovedly žádný zápis do databáze
|
|
|
|
|
|
|
|
**Přímý zápis do databáze**
|
|
|
|
- změny v DB se provedou okamžitě v době potřeby před potvrzením transakce
|
|
|
|
- v žurnálu je nutné uchovat staré hodnoty objektů
|
|
|
|
- v případě chyby se provádí _vycouvání_ transakce použitím metody `UNDO`
|
|
|
|
- výhoda: rychlé
|
|
|
|
+ při chybě disku, kde mám uložený žurnál, nelze použít
|
|
|
|
+ do žurnálu nutno zapisovat i operace čtení
|
|
|
|
+ novou hodnotu objektu zapsanou dosud nepotvrzenou transakcí může číst jiná transakce
|
|
|
|
+ při vycouvání aktuální transakce proto musí vycouvat i ty transakce, které četly nové hodnoty objektů
|
|
|
|
+ to může vést až k tzv. kaskádovému rušení transakcí
|
|
|
|
- známý také jako dominový efekt
|
|
|
|
- nejedná se o nějak častý jev
|
|
|
|
|
|
|
|
**Strategie obnovení přímého zápisu do DB**
|
|
|
|
- vytvoříme dva seznamy: `REDO` a `UNDO`
|
|
|
|
- do seznamu `UNDO` vložíme všechny transakce z kontrolního bodu
|
|
|
|
- seznam `REDO` zůstane prázdný
|
2024-01-16 13:43:12 +01:00
|
|
|
- žurnál procházíme od kontrolního bodu do předu
|
2024-01-08 23:05:31 +01:00
|
|
|
- narazíme-li na začátek transakce, vložíme ji do `UNDO`
|
|
|
|
- narazíme-li na konec transakce, převedeme ji z `UNDO` do `REDO`
|
|
|
|
- transakce zpracujeme metodou odpovídající názvu seznamu, ve kterém se nachází
|
|
|
|
|
|
|
|
## Paralelní zpracování transakcí
|
|
|
|
|
|
|
|
**Moduly SŘBD pro zpracování transakcí**
|
|
|
|
- z pohledu synchronizace nás ze SŘBD zajímají tyto moduly
|
|
|
|
- modul řízení transakcí (RT)
|
|
|
|
- transakce se na něj obracejí se žádostí o vykonání operace
|
|
|
|
- modul řízení obnovy databáze (RD)
|
|
|
|
- v databázi vykoná (realizuje) čtení/zápis podle požadavků plánovače
|
|
|
|
- plánovač
|
|
|
|
- zabezpečuje synchronizaci požadavků více transakcí v RT
|
|
|
|
- požadavky zařazuje do tzv. plánů (rozvrhů)
|
|
|
|
|
|
|
|
**Zadání příkladu**
|
|
|
|
- ve všech příkladech budeme označovat
|
|
|
|
- objekty (na disku) písmeny z konce abecedy
|
|
|
|
- interní proměnné ze začátku abecedy
|
|
|
|
- mějme
|
|
|
|
- počáteční hodnotu `X := 10`
|
|
|
|
- dvě transakce `T1` a `T2` mající shodnou činnost
|
|
|
|
|
|
|
|
| T1 | T2 |
|
|
|
|
| ---- | ---- |
|
|
|
|
| `A := read(X)` | |
|
|
|
|
| `A := A + 5` | |
|
|
|
|
| `write(X, A)` | |
|
|
|
|
| | `B := read(X)` |
|
|
|
|
| | `B := A + 5` |
|
|
|
|
| | `write(X, B)` |
|
|
|
|
- je několik možných plánů, kdy někde se může čtení z disku spustit dříve, než se zapíše předchozí výsledek
|
|
|
|
|
|
|
|
**Uspořádatelnost**
|
|
|
|
- serializovatelnost
|
|
|
|
- efekt paralelního zpracování transakcí musí být stejný, jako by byly transakce uspořádány v nějakém sériovém plánu
|
|
|
|
|
|
|
|
Příklad: původní hodnota `X := 10`
|
|
|
|
|
|
|
|
```python
|
|
|
|
# T1
|
|
|
|
A := read(X)
|
|
|
|
A := A + 5
|
|
|
|
write(X, A)
|
|
|
|
# T2
|
|
|
|
B := read(X)
|
|
|
|
B := B * 3
|
|
|
|
write(X, B)
|
|
|
|
```
|
|
|
|
|
|
|
|
- plán 1 (T1, T2), X = 45
|
|
|
|
- plán 2 (T2, T1), X = 35
|
|
|
|
+ paralelní běh transakcí může skončit jedním nebo druhým výsledkem
|
|
|
|
|
|
|
|
### Uzamykací protokoly
|
|
|
|
|
|
|
|
**Operace `LOCK(X)`**
|
|
|
|
- uzamknutí objektu X vyvolá transakce, aby ho ochránila před přístupem jiných transakcí
|
|
|
|
- objekt smí být uzamčen pouze jednou transakcí
|
|
|
|
- pokud chce objekt uzamknout ještě jiná transakce, je systémem pozastavena
|
|
|
|
|
|
|
|
**Operace `UNLOCK(X)`**
|
|
|
|
- odemknutí objektu X
|
|
|
|
- objekt může odemknout jen ta transakce, která jej uzamkla
|
|
|
|
- pokud na odemčení tohoto objetu čeká jiná transakce, může být opětovně spuštěna
|
|
|
|
|
|
|
|
**Dvoufázový (zamykací) protokol**
|
|
|
|
- lze dokázat, že uspořádatelnost plánu je zaručena, jestliže
|
|
|
|
- objekt může být v každém okamžiku uzamčen pouze pro jednu transakci
|
|
|
|
- jakmile transakce odemkne alespoň jeden objekt, nesmí už žádný objekt uzamknout
|
|
|
|
- poznámka
|
|
|
|
- nesmí uzamknout ani ten samý objekt, co odemkla (prostě nesmí žádný objekt uzamknout)
|
|
|
|
- porušení dvoufázového protokolu hrozí v případě, že si sami definujete a řídíte transakce
|
|
|
|
+ Two-phase locking (2PL)
|
|
|
|
+ fáze 1: růst (expanding)
|
|
|
|
+ transakce smějí pouze zamykat objekty, nesmí je odemykat
|
|
|
|
+ fáze 2: smršťování (shrinking)
|
|
|
|
+ transakce smějí pouze objekty odemykat, nesmí žádný objekt uzamknout
|
|
|
|
|
|
|
|
**Zamykání objektů**
|
|
|
|
- databázové objekty lze zamykat ve dvou režimech
|
|
|
|
- výlučný, též exklusivní režim
|
|
|
|
- sdílený režim
|
|
|
|
- výlučný režim
|
|
|
|
- objekt je uzamčen pro operace čtení i zápis
|
|
|
|
- nemůže být současně uzamčen jinou transakcí
|
|
|
|
- sdílený režim
|
|
|
|
- objekt je uzamčen jen pro operaci čtení
|
|
|
|
- daný objekt může být současně uzamčen v režimu čtení další transakcí
|
|
|
|
|
|
|
|
**Uváznutí** (deadlock)
|
|
|
|
- dodržení dvoufázového protokolu ještě neznamená odstranění všech potíží
|
|
|
|
- zásadní výhoda DB: transakce umí `ROLLBACK`
|
|
|
|
|
|
|
|
| T1 | T2 |
|
|
|
|
| --------- | --------- |
|
|
|
|
| `LOCK(X)` | |
|
|
|
|
| | `LOCK(Y)` |
|
|
|
|
| `LOCK(Y)` | |
|
|
|
|
| | `LOCK(X)` |
|
|
|
|
## Další protokoly
|
|
|
|
|
|
|
|
Musíme znát nějakou další informaci o objektech databáze, např. způsob jejich uložení
|
|
|
|
|
|
|
|
**Stromový uzamykací protokol** (Tree protocol)
|
|
|
|
- používá zámky
|
|
|
|
- pro hierarchické databáze
|
|
|
|
- reprezentace tzv. grafového protokolu
|
|
|
|
1. první výlučný zámek transakce T lze použít na jakýkoliv objekt X
|
|
|
|
2. další objekt může být uzamčen transakcí T pouze když byl v T uzamčen jeho předchůdce
|
|
|
|
3. objekty mohou být odemknuty kdykoliv
|
|
|
|
4. objekt, který byl v transakci T uzamknut a odemknut nesmí být už v T následovně znovu uzamknut
|
|
|
|
- všechny plány jsou uspořádatelné a nemůže dojít k uváznutí
|
|
|
|
|
|
|
|
**Protokol časových značek**
|
|
|
|
- místo zámků používá tzv. časové značky ČZ
|
|
|
|
- předává ji systém, tvoří rostoucí posloupnost
|
|
|
|
- plánovač transakcí vykonává konfliktní transakce (pracují nad stejným objektem X) v pořadí jejich ČZ
|
|
|
|
- takto navržené plány jsou uspořádatelné
|
|
|
|
- u každého objektu X jsou zaznamenávány největší značky
|
|
|
|
- pro čtení R_ČZ(X)
|
|
|
|
- pro zápis W_ČZ(X)
|
|
|
|
|
|
|
|
## Transakce v praxi
|
|
|
|
|
|
|
|
**Zajištění konzistence v SŘBD Oracle**
|
|
|
|
- konzistentní čtení (Multiversion Read consistency)
|
|
|
|
- na úrovni příkazu (Statement-Level Read Consistency)
|
|
|
|
- data získaná dotazem jsou vždy potvrzená
|
|
|
|
- na úrovni transakce (Transaction-Level Read Consistency)
|
|
|
|
- každý příkaz transakce vidí data nová, která byla transakcí zapsána
|
|
|
|
- ostatní transakce vidí data, která byla dostupná před začátkem transakce
|
|
|
|
- ke správě konzistentního čtení se využívají tzv. návratové segmenty
|
|
|
|
- uloženy v tzv. návratovém tabulkovém prostoru
|
|
|
|
|
|
|
|
**Nežádoucí jevy při čtení dat v transakcích**
|
|
|
|
|
|
|
|
- **Špinavé čtení** (Dirty read)
|
|
|
|
- též nepotvrzené čtení (Uncommited read)
|
|
|
|
- příklad
|
|
|
|
- transakce T1 aktualizuje vybraný záznam
|
|
|
|
- transakce T2 následně přečte tuto aktualizovanou hodnotu dříve, než proběhne její potvrzení
|
|
|
|
- problém nastane, když transakce T1 bude zrušena, tj. zavolá `ROLLBACK`
|
|
|
|
- potom transakce T2 přečetla hodnotu, která neměla existovat
|
|
|
|
|
|
|
|
+ **Neopakovatelné čtení** (Non-repeatable read)
|
|
|
|
- nastane, pokud čteme opakovaně stejnou hodnotu, ale v různých časech obdržíme různé hodnoty
|
|
|
|
- příklad
|
|
|
|
- transakce T1 přečte vybraný záznam
|
|
|
|
- transakce T2 následně daný záznam aktualizuje a bude potvrzena
|
|
|
|
- opětovné čtení stejného záznamu transakce T1 poskytne jiná data nebo také žádná
|
|
|
|
|
|
|
|
- **Fantomové čtení** (Phantom read)
|
|
|
|
- nastane, pokud při opakovaném čtení získáme nová data, která nebyla dostupná při prvním čtení
|
|
|
|
- příklad
|
|
|
|
- transakce T1 přečte záznamy, které vyhovují dotazu
|
|
|
|
- transakce T2 generuje nový záznam, která změní výsledek dotazu transakce T1
|
|
|
|
- opětovné vyhodnocení stejného dotazu transakce T1 poskytuje data navíc
|
|
|
|
|
|
|
|
**Úrovně izolace transakce dle normy**
|
|
|
|
|
|
|
|
- **Serializovatelná** (serializable)
|
|
|
|
- nejvyšší stupeň izolace
|
|
|
|
- dovoleno vykonávat pouze uspořádatelné plány
|
|
|
|
- transakce čeká, dokud záznamy uzamčené pro zápis ostatními transakcemi budou odemčeny
|
|
|
|
- transakce drží zámky buď pro čtení anebo pro zápis pro rozsah záznamů, které chce buď číst anebo ovlivnit zápisem
|
|
|
|
- rozsahem záznamů se rozumí výsledek selekce transakce
|
|
|
|
- pokud jiná transakce vloží/aktualizuje/smaže záznam, který do daného rozsahu zapadá, nebude jí zápis povolen
|
|
|
|
- transakce uvolňuje všechny zámky po jejím potvrzení nebo odvolání
|
|
|
|
|
|
|
|
+ **Opakovatelné čtení** (repeatable read)
|
|
|
|
- transakce čeká, dokud záznamy uzamčené pro zápis ostatními transakcemi budou odemčeny
|
|
|
|
- transakce drží
|
|
|
|
- zámky pro čtení pro záznamy, které chce číst
|
|
|
|
- zámky pro zápis pro záznamy, které chce vkládat/aktualizovat/mazat
|
|
|
|
- jiná transakce může vložit/aktualizovat ty záznamy, které spadají do rozsahu záznamů uzamčených pro čtení
|
|
|
|
- transakce uvolňuje všechny zámky po jejím potvrzení nebo odvolání
|
|
|
|
|
|
|
|
- **Potvrzené čtení** (read commited)
|
|
|
|
- transakce čeká, dokud záznamy uzamčené pro zápis ostatními transakcemi budou odemčeny
|
|
|
|
- transakce drží
|
|
|
|
- zámek pro čtení pro aktuálně čtený záznam
|
|
|
|
- zámek pro zápis záznamu, který chce aktualizovat/mazat
|
|
|
|
- transakce uvolňuje
|
|
|
|
- zámek pro čtení po přečtení aktuálního záznamu
|
|
|
|
- zámky pro zápis po potvrzení nebo odvolání transakce
|
|
|
|
|
|
|
|
+ **Nepotvrzené čtení** (read uncommited)
|
|
|
|
- nejnižší stupeň izolace
|
|
|
|
- transakce není izolovaná od ostatních transakcí
|
|
|
|
- obvykle je tato úroveň použita u transakcí v režimu čtení
|
|
|
|
- čte i nepotvrzené záznamy jiných transakcí
|
|
|
|
|
|
|
|
| | špinavé čtení | neopakovatelné čtení | fantomové čtení |
|
|
|
|
| ----------------------- | -------------- | -------------------- | --------------- |
|
|
|
|
| serializovatelná úroúveň | nevyskytuje se | nevyskytuje se | nevyskytuje se |
|
|
|
|
| opakované čtení | nevyskytuje se | nevyskytuje se | VYSKYTUJE SE |
|
|
|
|
| potvrzené čtení | nevyskytuje se | VYSKYTUJE SE | VYSKYTUJE SE |
|
|
|
|
| nepotvrzené čtení | VYSKYTUJE SE | VYSKYTUJE SE | VYSKYTUJE SE |
|
|
|
|
**Izolace transakce v SŘBD Oracle**
|
|
|
|
- Read Commited Isolation Level
|
|
|
|
- výchozí úroveň
|
|
|
|
- transakce vidí data dostupná před začátkem transakce
|
|
|
|
- dovoluje jevy neopakovatelné a fantomové čtení
|
|
|
|
- trpí efektem ztráty aktualizace dat (lost update)
|
|
|
|
- Serializable Isolation Level
|
|
|
|
- transakce vidí potvrzené změny v čase začátku transakce a změny provedené v transakci
|
|
|
|
- brání všem nežádoucím jevům čtení, netrpí efektem ztráty aktualizace dat
|
|
|
|
- Read-Only Isolation Level
|
|
|
|
- podobné jako předchozí úroveň
|
|
|
|
- transakce nemají přístup k datům, které modifikují jiné transakce
|
|
|
|
|
|
|
|
**Ztráta aktualizace**
|
|
|
|
- nastane, pokud souběžné transakce modifikují hodnotu stejného záznamu
|
|
|
|
- zůstane zapsaná až poslední změna, předchozí se ztratí
|
|
|
|
- příklad
|
|
|
|
- transakce T1 modifikuje hodnotu konkrétního záznamu
|
|
|
|
- transakce T2 také později chce modifikovat hodnotu stejného záznamu, ale je pozastavena
|
|
|
|
- transakce T1 bude poté potvrzena, následně dojde k modifikaci dat transakce T2
|
|
|
|
- transakce T2 bude potvrzena
|
|
|
|
|
|
|
|
**Nastavení úrovně izolace**
|
|
|
|
- na úrovni transakce
|
|
|
|
```sql
|
|
|
|
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
|
|
|
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
|
|
SET TRANSACTION ISOLATION LEVEL READONLY;
|
|
|
|
```
|
|
|
|
|
|
|
|
- na úrovni aktuálního spojení
|
|
|
|
```sql
|
|
|
|
ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
|
|
|
|
ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE;
|
|
|
|
ALTER SESSION SET ISOLATION_LEVEL READONLY;
|
|
|
|
```
|