Skip to content
Snippets Groups Projects
Commit 6aff4e91 authored by Martin Mareš's avatar Martin Mareš
Browse files

Bezpečné transakce při zakládání uživatelů/účastníků/účastí

Closes #314:

Pokud organizátor odešle POST na přidání nového účastníka soutěže
dvakrát rychle po sobě (třeba kvůli nějakému automatickému retry
po rozpadu spojení), dvě různé DB transakce se snaží založit uživatele
se stejným loginem. Jedna z nich selže na unikátnosti sloupce email.

V defaultní úrovni izolace transakcí (READ COMMITTED) to nemá žádné
hezké řešení. Nepomůže SELECT ... FOR UPDATE, jelikož ten zamyká pouze
nalezené řádky, nikoliv neexistenci dalších řádků vyhovujících podmínce.

Co by se dalo dělat:

(1) Zvýšit úroveň izolace aspoň na READ REPEATABLE. To vyřeší problém,
    ale současně může začít víceméně jakákoliv zapisující transakce
    failovat. Vyžadovalo by dopsat retry do prakticky všech míst v OSMO,
    kde je nějaký commit.

(2) Retryovat specificky transakce na zakládání užívatelů (a účastí apod.).
    Tohle nejde snadno, jelikoz jsou i součástí dlouho běžících transakcí
    v importech (zatím jsme se snažíli, aby byl celý import atomický
    a v případě selhání se celý rollbackoval). To by možná mohly vyřešit
    subtransakce.

(3) Zamykat celou tabulku s uživateli, než na ní provedeme první SELECT.
    To by asi vyřešilo problém, ale byl by potřeba zápisový zámek, takže
    by paralelně nemohla běžet žádná čtení. A také by se to potenciálně
    mohlo deadlockovat (potřebujeme v jedné transakci postupně lock na
    uživatele, účastníky a účasti a locky platí až do konce transakce).

(4) Používat INSERT ... ON CONFLICT <něco>. To vypadá bezpečně, jen to není
    moc pohodlné, zejména proto, že s tím nepočítá ORM, takže je potřeba
    dělat všechno ručně.

Zatím jsem zvolil (4), protože mi přijde, že to změny udržuje lokální
a funguje i s dlouhými transakcemi při importu. Výhledově bych se ale
chtěl zamyslet nad tím, jak takové věci řešit co nejuniverzálněji
a nejpohodlněji.
parent 37185c2f
No related branches found
No related tags found
1 merge request!129Bezpečné transakce při zakládání uživatelů/účastníků/účastí
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment