Voor iedereen die googelt en probeert te begrijpen waarom hun drop-tabel (of externe sleutel laten vallen of externe sleutel toevoegen) lange tijd vastliep:
PostgreSQL (Ik heb versies 9.4 tot 13 bekeken) foreign key constraints worden feitelijk geïmplementeerd met behulp van triggers aan beide uiteinden van de refererende sleutel .
Als u een bedrijfstabel hebt (id als primaire sleutel) en een bankrekeningtabel (id als primaire sleutel, company_id als externe sleutel die naar company.id verwijst), dan zijn er eigenlijk 2 triggers op de bankrekeningtabel en ook 2 triggers op het bedrijf tafel.
tabelnaam | timing | trigger_name | functienaam |
---|---|---|---|
bankrekening | NA UPDATE | RI_ConstraintTrigger_c_1515961 | RI_FKey_check_upd |
bankrekening | NA INSERT | RI_ConstraintTrigger_c_1515960 | RI_FKey_check_ins |
bedrijf | NA UPDATE | RI_ConstraintTrigger_a_1515959 | RI_FKey_noaction_upd |
bedrijf | NA VERWIJDEREN | RI_ConstraintTrigger_a_1515958 | RI_FKey_noaction_del |
De initiële creatie van die triggers (bij het maken van de foreing-sleutel) vereist SHARE ROW EXCLUSIVE lock op die tabellen (het was ACCESS EXCLUSIVE lock in versie 9.4 en eerder). Deze vergrendeling is niet in strijd met "gegevensleesvergrendelingen", maar zal conflicteren met alle andere vergrendelingen, bijvoorbeeld een eenvoudige INSERT/UPDATE/DELETE in de bedrijfstabel.
Het verwijderen van die triggers (bij het laten vallen van de externe sleutel of de hele tabel) vereist ACCESS EXCLUSIVE lock op die tabellen. Dit slot conflicteert met elk ander slot!
Stelt u zich dus een scenario voor waarin u een transactie A hebt lopen die eerst een eenvoudige SELECTEER uit de bedrijfstabel deed (waardoor het een ACCESS SHARE-vergrendeling voor de bedrijfstafel vasthield totdat de transactie is vastgelegd of teruggedraaid) en nu ander werk doet voor 3 minuten. U probeert de bank_rekeningtabel in transactie B te laten vallen. Dit vereist ACCESS EXCLUSIVE-vergrendeling, die moet wachten tot de ACCESS SHARE-vergrendeling eerst wordt vrijgegeven. Daarnaast alle andere transacties, die toegang willen tot de bedrijfstabel (gewoon SELECT, of misschien INSERT/UPDATE/DELETE), worden in de wachtrij geplaatst om te wachten op het ACCESS EXCLUSIVE-slot, dat wacht op het ACCESS SHARE-slot.
Langlopende transacties en DDL-wijzigingen vereisen een delicate behandeling.