Řešení problémů se zablokováním v postgresqlu

V ideálním výrobním prostředí bychom všichni čelili situaci, kdy z naší databáze dostaneme patovou situaci. Váš stůl (y) může mít několik důvodů, jak se dostat do slepé uličky. Projdeme si několik scénářů a možných oprav, abychom zvládli zablokování.

Scénář 1: Nejběžnější scénář.

Vlákno 1: aktualizace názvu sady zaměstnanců = 'ram', kde id = 1

→ Tento příkaz zamkne řádek, kde id = 1

Vlákno 2: aktualizace názvu sady zaměstnanců = 'akash', kde id = 2

→ Tento příkaz zamkne řádek, kde id = 2

Vlákno 1: aktualizujte název sady zaměstnanců = 'prasanna', kde id = 2

→ Tento příkaz se pokusí získat zámek v tomto řádku, ale nemůže, protože zámek již byl vytvořen pomocí vlákna2. Bude tedy čekat, až vlákno 2 uvolní zámek.

Vlákno 2: aktualizace názvu sady zaměstnanců = 'prashant', kde id = 1

→ Tento příkaz se pokusí získat zámek v tomto řádku, ale nemůže, protože zámek již byl vytvořen pomocí vlákna1. Bude tedy čekat, až vlákno1 uvolní zámek, což se nikdy nestane, protože oba drží zámek proti sobě a vytvoří tak zablokování.

Scénář 2:

Při současném zpracování stejného požadavku.

Závit 1:

aktualizace zaměstnanecké sady role = 'dev' kde jméno v ('ram', 'prashant', 'aakash')

→ IN klauzule nemusí provést aktualizaci v určeném pořadí. Výše uvedený příkaz může například provést aktualizaci v následujícím pořadí „prashant“, „aakash“, „ram“.

Závit 2:

aktualizace zaměstnanecké sady role = 'dev' kde jméno v ('ram', 'prashant', 'aakash')

→ Platí zde stejná podmínka od vlákna 1 a výše uvedený příkaz může provést dotaz v tomto pořadí → 'ram', 'prashant', 'aakash'

Tak co je za problém ?

Vlákno 1, nejprve uzamkne řádek kde name = 'prashant' a Thread2, uzamkne řádek s názvem = 'ram', dostaneme opět uváznutí, protože další sada příkazů bude záviset na každé z těchto transakcí k uvolnění zámku.

Jak tedy zvládneme zablokování?

V PostgreSQL máme možnost zamknout všechny řádky uvnitř transakce najednou a uvolnit je všechny jednou po dokončení transakce.

Vezměme si příklad, jak to skutečně můžeme udělat,

ZAČÍT;

VYBERTE 1 od zaměstnance, pokud je v (1,2,3) NA AKTUALIZACI;

aktualizace zaměstnance set role = 'dev' kde jméno v ('ram', 'prashant', 'aakash');

KONEC;

pomocí SELECT… FOR UPDATE použije zámek na všechny řádky najednou určené ve stavu kde, čímž uvolní zámek jednou po dokončení transakce. Cool není to :)

Buďte opatrní při používání SELECT… FOR UPDATE, protože to má dopad na sloupec cizího klíče a referenční tabulku. Pokud má referenční tabulka specificky změnu v referenčním poli, bude uzamčena, dokud není transakce dokončena.

Děkujeme za přečtení tohoto blogu. Doufám, že to pomůže :)