За всеки, който търси в Google и се опитва да разбере защо тяхната таблица за премахване (или премахване на външен ключ или добавяне на външен ключ) е блокирала за дълго време:
PostgreSQL (Разгледах версии от 9.4 до 13) ограниченията на външния ключ всъщност се прилагат с помощта на тригери в двата края на външния ключ .
Ако имате таблица company (id като първичен ключ) и таблица bank_account (id като първичен ключ, company_id като външен ключ, сочещ към company.id), тогава всъщност има 2 тригера на таблицата bank_account и също 2 тригера на company таблица.
име_на_таблица | време | trigger_name | име_на_функция |
---|---|---|---|
банкова_сметка | СЛЕД АКТУАЛИЗАЦИЯ | RI_ConstraintTrigger_c_1515961 | RI_FKey_check_upd |
банкова_сметка | СЛЕД ВМЪКВАНЕ | RI_ConstraintTrigger_c_1515960 | RI_FKey_check_ins |
компания | СЛЕД АКТУАЛИЗАЦИЯ | RI_ConstraintTrigger_a_1515959 | RI_FKey_noaction_upd |
компания | СЛЕД ИЗТРИВАНЕ | RI_ConstraintTrigger_a_1515958 | RI_FKey_noaction_del |
Първоначалното създаване на тези тригери (когато се създава външният ключ) изисква SHARE ROW EXCLUSIVE заключване на тези таблици (преди беше ACCESS EXCLUSIVE заключване във версия 9.4 и по-стари). Това заключване не е в конфликт с „заключвания за четене на данни“, но ще бъде в конфликт с всички други заключвания, например просто INSERT/UPDATE/DELETE в таблицата на компанията.
Изтриването на тези тригери (при изпускане на външния ключ или цялата таблица) изисква заключване ИЗКЛЮЧИТЕЛЕН ДОСТЪП на тези таблици. Тази ключалка е в конфликт с всяка друга ключалка!
Така че си представете сценарий, при който имате изпълнявана транзакция A, която първо е направила прост SELECT от таблицата на компанията (което я кара да задържи заключване на ACCESS SHARE за таблицата на компанията, докато транзакцията бъде ангажирана или върната назад) и сега върши друга работа за 3 минути. Опитвате се да премахнете таблицата bank_account в транзакция B. Това изисква заключване ACCESS EXCLUSIVE, което ще трябва да изчака, докато заключването ACCESS SHARE бъде освободено първо. В допълнение към това всички други транзакции, които искат достъп до таблицата на компанията (просто ИЗБЕРЕТЕ, или може би INSERT/UPDATE/DELETE), ще бъдат поставени на опашка за изчакване на ключалката ACCESS EXCLUSIVE, която чака заключването на ACCESS SHARE.
Продължителните транзакции и DDL промените изискват деликатно боравене.