Pro každého, kdo googluje a snaží se pochopit, proč se jejich tabulka přetažení (nebo zahození cizího klíče nebo přidání cizího klíče) na dlouhou dobu zasekla:
PostgreSQL (Podíval jsem se na verze 9.4 až 13) omezení cizího klíče jsou ve skutečnosti implementována pomocí spouštěčů na obou koncích cizího klíče .
Pokud máte tabulku společnosti (id jako primární klíč) a tabulku bank_account (id jako primární klíč, company_id jako cizí klíč ukazující na company.id), pak jsou v tabulce bank_account 2 spouštěče a také 2 spouštěče na společnosti. tabulka.
název_tabulky | načasování | trigger_name | název_funkce |
---|---|---|---|
bankovní_účet | PO AKTUALIZACI | RI_ConstraintTrigger_c_1515961 | RI_FKey_check_upd |
bankovní_účet | PO VLOŽENÍ | RI_ConstraintTrigger_c_1515960 | RI_FKey_check_ins |
společnost | PO AKTUALIZACI | RI_ConstraintTrigger_a_1515959 | RI_FKey_noaction_upd |
společnost | PO SMAZÁNÍ | RI_ConstraintTrigger_a_1515958 | RI_FKey_noaction_del |
Počáteční vytvoření těchto spouštěčů (při vytváření cizího klíče) vyžaduje zámek SHARE ROW EXCLUSIVE na těchto tabulkách (ve verzi 9.4 a dřívějších to býval zámek ACCESS EXCLUSIVE). Tento zámek není v konfliktu se "zámky čtení dat", ale bude v konfliktu se všemi ostatními zámky, například jednoduchým INSERT/UPDATE/DELETE do firemní tabulky.
Odstranění těchto spouštěčů (při zahození cizího klíče nebo celé tabulky) vyžaduje zámek ACCESS EXCLUSIVE na těchto tabulkách. Tento zámek je v konfliktu s každým jiným zámkem!
Představte si tedy scénář, kdy máte spuštěnou transakci A, která nejprve provedla jednoduchý SELECT z tabulky společnosti (což způsobilo, že podržela zámek ACCESS SHARE pro tabulku společnosti, dokud není transakce potvrzena nebo vrácena zpět) a nyní provádí nějakou jinou práci pro 3 minuty. Pokoušíte se zrušit tabulku bank_account v transakci B. To vyžaduje zámek ACCESS EXCLUSIVE, který bude muset počkat, dokud se nejprve neuvolní zámek ACCESS SHARE. Kromě toho všechny ostatní transakce, které chtějí získat přístup k tabulce společnosti (stačí SELECT, nebo možná INSERT/UPDATE/DELETE), bude zařazen do fronty, aby čekal na zámek ACCESS EXCLUSIVE, který čeká na zámek ACCESS SHARE.
Dlouhodobě probíhající transakce a změny DDL vyžadují citlivé zacházení.