Ahojte všetci. Tu je Vladislav Rodin. V súčasnosti som vedúcim kurzu "Architekt vysokých zaťažení" na OTUS a tiež učím na kurzoch zameraných na architektúru softvéru.
Okrem učenia, ako ste mohli všimnúť, sa zaoberám písaním autorských materiálov pre blog OTUS na habri a dnešný článok chcem venovať spusteniu kurzu , na ktorý je momentálne otvorený zápis.

Úvod
V sme hovorili o tom, že transakcie v databázach slúžia na riešenie dvoch úloh: zabezpečenie odolnosti voči poruchám a prístup k dátam v konkurenčnom prostredí. Pre riadne vykonávanie týchto úloh musí transakcia disponovať vlastnosťami ACID. Dnes podrobne preberieme písmeno I (izolácia) v tejto skratke.
Izolácia
Izolácia rieši problém prístupu k dátam v konkurenčnom prostredí, pričom fakticky poskytuje ochranu pred race conditions. Ideálne, izolácia znamená serializáciu, teda vlastnosť, ktorá zabezpečuje, že výsledok vykonania transakcií paralelne bude taký istý, ako keby sa vykonávali sekvenčne. Hlavný problém tejto vlastnosti spočíva v tom, že je veľmi ťažké ju technicky zabezpečiť, a preto výrazne zaťažuje výkon systému. Práve preto sa izolácia často oslabuje, pričom sa berú na seba riziká vzniku určitých anomálií, o ktorých sa vyjadrujem nižšie. Možnosť vzniku rôznych anomálií presne charakterizuje úroveň izolácie transakcií.
Najznámejšími anomáliami sú: dirty read, non-repeatable read, phantom read, ale v skutočnosti ich je ešte 5: dirty write, cursor lost update, lost update, read skew, write skew.
Dirty write
Podstata anomálie spočíva v tom, že transakcie môžu prepisovať nezakompilované dáta.

Táto anomália je nebezpečná nielen tým, že dáta môžu byť v konflikte po potvrdení oboch transakcií (ako na obrázku), ale aj tým, že narušuje atomickosť: pretože povolíme prepísanie nezakompilovaných dát, nie je jasné, ako vrátiť jednu transakciu, aniž by sme sa dotkli druhej.
Anomáliu je možné celkom jednoducho vyriešiť: pred začiatkom zápisu umiestnite zámok na zápis, čím sa iným transakciám zakáže meniť záznam, kým nie je zámok zrušený.
Dirty read
Dirty read znamená čítanie nezakomitovaných dát.

Problémy nastávajú, keď je potrebné na základe vzorky vykonať nejaké akcie alebo prijať rozhodnutia.
Na opravu anomálie je možné nastaviť blokovanie na čítanie, no to výrazne zasiahne do výkonu. Oveľa jednoduchšie je povedať, že pre rollback transakcie musí byť pôvodný stav dát (pred začiatkom zápisu) nevyhnutne uložený v systéme. Prečo by sme ho nemali čítať odtiaľ? Je to dosť lacné, preto väčšina databáz predvolene vypína dirty read.
Stratené aktualizácie
Stratené aktualizácie znamenajú stratené aktualizácie a preklad dostatočne presne vystihuje podstatu problému:

V skutočnosti bola výsledok transakcie T2 zrušená. Takáto situácia sa opravuje explicitnými alebo implicitnými blokovaniami záznamu. Čiže buď jednoducho realizujeme aktualizáciu záznamu, čím vzniká implicitné blokovanie, alebo vykonávame select for update, čím spôsobujeme vznik blokovania na čítanie a zápis. Upozorňujeme, že takáto operácia je dosť nebezpečná: svojím "nevinným" čítaním blokujeme iné čítania. Niektoré databázy ponúkajú bezpečnejší select for share, ktorý umožňuje čítať dáta, ale nezabezpečuje ich zmenu.
Stratené aktualizácie kurzora
Pre jemnejšiu kontrolu môžu databázy ponúkať iné nástroje, napríklad kurzor. Kurzory sú štruktúry, ktoré obsahujú súbor riadkov a umožňujú iteráciu po nich. declare cursor_name for select_statement. Obsah kurzora je popísaný výberom.
Na čo je potrebný kurzor? Ide o to, že niektoré databázy ponúkajú blokovanie na všetky záznamy vybrané výberom (read stability), alebo iba na ten záznam, na ktorom sa práve kurzor nachádza (cursor stability). Pri cursor stability dochádza k krátkemu zablokovaniu, čo znižuje počet blokovaní v prípade, že prechádzame veľkou vzorkou dát. Preto sa anomália stratených aktualizácií pre kurzor vyčleňuje osobitne.
Nerepetovateľné čítanie
Nerepetovateľné čítanie spočíva v tom, že počas vykonávania našej transakcie 2 po sebe idúce čítania rovnakého záznamu povedú k získaniu rôznych výsledkov, pretože iná transakcia zasiahla medzi týmito dvoma čítaniami, zmenila naše dáta a bola potvrdená.

Prečo je to vlastne problém? Predstavte si, že cieľom transakcie T2 na obrázku je vybrať všetky produkty, ktorých cena je nižšia ako 150 eur. Niekto iný aktualizoval cenu na 200 eur. Takto filter nefunguje.
Dáta anomálie prestávajú vznikajú pri pridávaní dvojfázových zámkov alebo pri použití mechanizmu MVCC, o čom by som chcel hovoriť osobitne.
Fantomové čítanie
Fantomovým sa nazýva čítanie dát, ktoré boli pridané inou transakciou.

Ako príklad môžeme pozorovať nesprávny výber najlacnejšieho produktu pri vzniku tejto anomálie.
Zbaviť sa fantómových čítaní je už dosť náročné. Obvyklé zámky nestačia, pretože nemôžeme uzamknúť to, čo ešte neexistuje. Systémy 2PL používajú predikčné zámky, kým MVCC systémy plánovač transakcií zruší transakcie, ktoré môžu byť narušené vložením. Ako prvý, tak druhý mechanizmus sú dosť náročné.
Read skew
Read skew vzniká, keď pracujeme s niekoľkými tabuľkami, ktorých obsah by sa mal meniť súhlasne.
Predpokladajme, že existujú tabuľky, ktoré reprezentujú príspevky a ich metainformácie:

Jedna transakcia číta z tabuliek, iná ich mení:

V dôsledku vykonania transakcie T1 má príspevok title = Good a updated_by = T2, čo predstavuje určité nesúlad.
V skutočnosti ide o non-repeatable read, ale v kontexte viacerých tabuliek.
Na opravu môže T1 uzamknúť všetky riadky, ktoré bude čítať, čo zabráni transakcii T2 meniť informácie. V prípade MVCC bude transakcia T2 zrušená. Ochrana proti tejto anomálii môže byť dôležitá, ak používame kurzory.
Write skew
Túto anomáliou je tiež jednoduchšie vysvetliť na príklade: predpokladajme, že v našom systéme musí byť aspoň jeden doktor na službe, ale obaja lekári sa rozhodli svoju službu zrušiť:


Anomália viedla k tomu, že žiadny z lekárov sa neobjaví na službe. Prečo sa to stalo? Pretože transakcia kontrolovala podmienku, ktorú môže narušiť iná transakcia, a kvôli izolácii sme nevideli túto zmenu.
Je to to isté non-repeatable read. Ako alternatíva môžu selecty uzamknúť tieto záznamy.
Zápisový skew a čítací skew sú kombináciou predchádzajúcich anomálií. Môžeme sa pozrieť na zápisový skew, ktorý je v podstate phantom read. Zoberme si tabuľku, v ktorej sú mená zamestnancov, ich mzdy a projekt, na ktorom pracujú:


Nakoniec dostaneme nasledujúci obraz: každý manažér si myslel, že jeho zmena nevedie k prekročeniu rozpočtu, preto uskutočnili personálne zmeny, ktoré celkovo viedli k prečerpaniu.
Príčina vzniku problému je presne taká istá ako pri phantom read.
Zhrnutie
Zníženie úrovne izolácie transakcií v databáze je kompromis medzi bezpečnosťou a výkonnosťou, k výberu tejto úrovne by sa malo pristupovať z pohľadu potenciálnych rizík pre podnik pri vzniku rôznych anomálií.
Zdroj: habr.com
