sql >> Database >  >> RDS >> PostgreSQL

Vermijd exclusieve toegangsvergrendelingen op tabellen waarnaar wordt verwezen bij DROPping in PostgreSQL

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.



  1. VBA Runtime-fout '-2147467259 (80004005)

  2. Hoe kan ik MySQL-fout #1064 oplossen?

  3. COUNT gebruiken in GROUP_CONCAT

  4. Hoe rijen te filteren op geneste waarden in een json-kolom?