Ahoj všem. Tady je Vladislav Rodin. V současné době jsem vedoucím kurzu „Architekt vysoce zatížených systémů“ na OTUS a také vyučuji na kurzech zaměřených na architekturu softwaru.
Kromě vyučování, jak možná víte, se věnuji psaní autorského materiálu pro blog OTUS na Habr a dnešní článek bych chtěl věnovat spuštění kurzu , pro který je právě nyní otevřen zápis.

Úvod
V Mluvili jsme o tom, že transakce v databázích slouží k řešení dvou úkolů: zajištění odolnosti vůči chybám a přístupu k datům v konkurenčním prostředí. Aby tyto úkoly byly plně splněny, musí mít transakce vlastnosti ACID. Dnes se podrobně podíváme na písmeno I (izolace) v této zkratce.
Izolace
Izolace řeší problém přístupu k datům v konkurenčním prostředí, čímž ve skutečnosti poskytuje ochranu před race conditions. Ideálně znak izolace znamená serializaci, tedy vlastnost, která zajišťuje, že výsledek provádění transakcí paralelně je stejný, jako kdyby byly prováděny sekvenčně. Hlavní problém této vlastnosti spočívá v tom, že je technicky velmi obtížné ji zajistit, a jako důsledek to značně ovlivňuje výkonnost systému. Právě proto se izolace často oslabuje, přičemž se přijímají rizika vzniku některých anomálií, o kterých si povíme níže. Možnost vzniku různých anomálií právě charakterizuje úroveň izolace transakcí.
Nejznámějšími anomáliemi jsou: dirty read, non-repeatable read, phantom read, ale ve skutečnosti jich je ještě 5: dirty write, cursor lost update, lost update, read skew, write skew.
Dirty write
Podstatou této anomálie je, že transakce mohou přepisovat nezamčená data.

Tato anomálie je nebezpečná nejen tím, že data se mohou po potvrzení obou transakcí dostat do konfliktu (jak je znázorněno na obrázku), ale také tím, že narušuje atomaritu: protože umožňujeme přepisovat nezamčená data, není jasné, jak vrátit jednu transakci, aniž by se to dotklo druhé.
Tato anomálie se léčí dost jednoduše: před počátkem zápisu nastavíme zámek na zápis, čímž zakážeme ostatním transakcím měnit zápis, dokud není zámek odstraněn.
Dirty read
Dirty read znamená přečtení nezamčených dat.

Problémy nastávají, když je třeba na základě výběru provést nějaké akce nebo přijmout rozhodnutí.
Pro opravu anomálie je možné zavést blokaci pro čtení, ale to by mělo značný dopad na výkon. Mnohem jednodušší je říct, že pro rollback transakce musí být původní stav dat (před zahájením zápisu) nutně zachován v systému. Proč nečíst odtud? To je dost levné, a proto většina databází ve výchozím nastavení zakazuje dirty read.
Ztracené aktualizace
Ztracené aktualizace znamenají ztracené aktualizace, a překlad celkem přesně vystihuje podstatu problému:

Ve skutečnosti byla výsledná transakce T2 zrušena. Tato situace se řeší explicitními nebo implicitními blokacemi záznamu. To znamená, že buď provedeme aktualizaci záznamu, a tím dojde k implicitní blokaci, nebo vykonáme select for update, což vyvolává blokaci pro čtení a zápis. Všimněte si, že tato operace je dost nebezpečná: svým "nevinným" čtením blokujeme další čtení. Některé databáze nabízejí bezpečnější select for share, které umožňuje číst data, ale neumožňuje je měnit.
Ztracená aktualizace kurzoru
Pro podrobnější kontrolu mohou databáze nabízet další nástroje, například kurzor. Kurzorem se rozumí struktura obsahující sadu řádků a umožňující jejich iteraci. declare cursor_name for select_statement. Obsah kurzoru je popsán selektem.
Proč potřebujeme kurzor? Jedná se o to, že některé databáze nabízejí blokaci pro všechny záznamy vybrané selektem (read stability), nebo pouze na záznamu, na kterém se v tu chvíli kurzor nachází (cursor stability). Při cursor stability dochází k krátké blokaci, což snižuje počet blokací, pokud iterujeme přes velký výběr dat. Anomálie ztracené aktualizace je proto pro kurzor vyčleněna zvlášť.
Nerepeatable read
Nerepeatable read spočívá v tom, že během provádění naší transakce 2 po sobě jdoucí čtení stejného záznamu povedou k získání různých výsledků, protože jiná transakce zasáhla mezi těmito dvěma čteními, změnila naše údaje a byla zkomitována.

Proč je to vůbec problém? Představte si, že cílem transakce T2 na obrázku je vybrat všechny produkty, jejichž cena je nižší než 150 měn. Někdo jiný aktualizoval cenu na 200 měn. Tímto se aplikovaný filtr neprojevil.
Tyto anomálie přestávají vznikat při použití dvoufázového blokování nebo mechanismu MVCC, o čemž bych chtěl mluvit zvlášť.
Fantomové čtení
Fantomovým se nazývá čtení dat, která byla přidána jinou transakcí.

Jako příklad si můžeme představit nesprávný výběr nejlevnějšího produktu při vzniku této anomálie.
Zbavit se fantomových čtení je již dosti složité. Běžné blokování nestačí, protože nemůžeme zablokovat to, co ještě neexistuje. Systémy 2PL používají predikativní blokování, zatímco systémy MVCC plánovač transakcí ruší transakce, které mohou být narušeny vložením. Jak první, tak druhý mechanismus je dost objemný.
Read skew
Read skew vzniká, když pracujeme s několika tabulkami, jejichž obsah by se měl měnit souběžně.
Předpokládejme, že máme tabulky, které reprezentují příspěvky a jejich meta informace:

Jedna transakce čte z tabulek, druhá je mění:

V důsledku provedení transakce T1 má příspěvek title = Good a updated_by = T2, což je určité nesoulad.
V podstatě se jedná o non-repeatable read, ale v rámci několika tabulek.
Pro opravu může T1 aplikovat blokování na všechny řádky, které bude číst, což transakci T2 zabrání v měnění informací. V případě MVCC bude transakce T2 zrušena. Ochrana před touto anomálií může být důležitá, pokud používáme kurzory.
Write skew
Tuto anomálii také jednoduše vysvětlíme na příkladu: předpokládejme, že v našem systému musí být alespoň jeden lékař na pohotovosti, ale oba lékaři se rozhodli svou pohotovost zrušit:


Anomálie vedla k tomu, že žádný lékař nepřijde na pohotovost. Proč se to stalo? Protože transakce kontrolovala podmínku, kterou může narušit jiná transakce, a kvůli izolaci jsme tuto změnu neviděli.
Je to stejné jako non-repeatable read. Jako možnost mohou selecty aplikovat blokování na tyto záznamy.
Zápisová a čtecí zkreslení jsou kombinacemi předchozích anomálií. Můžeme považovat zápisové zkreslení za v podstatě fantomové čtení. Zvažme tabulku, která obsahuje jména zaměstnanců, jejich platy a projekty, na kterých pracují:


Na závěr dostáváme následující obraz: každý manažer si myslel, že jeho změna nezpůsobí překročení rozpočtu, proto provedli personální změny, které dohromady vedly k překročení nákladů.
Důvod vzniku problému je přesně takový, jaký byl u fantomového čtení.
Závěry
Snížení úrovně izolace transakcí v databázi je kompromisem mezi bezpečností a výkonem, k volbě této úrovně je třeba přistupovat s ohledem na potenciální rizika pro podnikání v případě vzniku různých anomálií.
Zdroj: habr.com
