Для тех, кто ищет в Google и пытается понять, почему их таблица удаления (или удаление внешнего ключа или добавление внешнего ключа) застряла на долгое время:
PostgreSQL (я смотрел версии с 9.4 по 13) ограничения внешнего ключа на самом деле реализуются с помощью триггеров на обоих концах внешнего ключа.
Если у вас есть таблица компании (идентификатор в качестве первичного ключа) и таблица bank_account (идентификатор в качестве первичного ключа, company_id в качестве внешнего ключа, указывающего на company.id), то на самом деле в таблице bank_account есть 2 триггера, а также 2 триггера в компании. стол.
table_name |
timing |
trigger_name |
function_name |
bank_account |
AFTER UPDATE |
RI_ConstraintTrigger_c_1515961 |
RI_FKey_check_upd |
bank_account |
AFTER INSERT |
RI_ConstraintTrigger_c_1515960 |
RI_FKey_check_ins |
company |
AFTER UPDATE |
RI_ConstraintTrigger_a_1515959 |
RI_FKey_noaction_upd |
company |
AFTER DELETE |
RI_ConstraintTrigger_a_1515958 |
RI_FKey_noaction_del |
Первоначальное создание этих триггеров (при создании внешнего ключа) требует блокировки SHARE ROW EXCLUSIVE для этих таблиц (раньше это была блокировка ACCESS EXCLUSIVE в версии 9.4 и ранее). Эта блокировка не конфликтует с блокировками чтения данных, но будет конфликтовать со всеми другими блокировками, например, простой INSERT/UPDATE/DELETE в таблицу компании.
Для удаления этих триггеров (при удалении внешнего ключа или всей таблицы) требуется блокировка ACCESS EXCLUSIVE для этих таблиц. Этот замок конфликтует с любым другим замком!
Итак, представьте себе сценарий, в котором у вас есть работающая транзакция A, которая сначала выполнила простой SELECT из таблицы компании (заставив ее удерживать блокировку ACCESS SHARE для таблицы компании до тех пор, пока транзакция не будет зафиксирована или не будет отменена), а теперь выполняет какую-то другую работу для 3 минуты. Вы пытаетесь удалить таблицу bank_account в транзакции B. Для этого требуется блокировка ACCESS EXCLUSIVE, которая должна будет подождать, пока сначала не будет снята блокировка ACCESS SHARE. Кроме того, все другие транзакции, которые хотят получить доступ к таблице компаний (просто SELECT или, возможно, INSERT/UPDATE/DELETE), будут поставлены в очередь для ожидания блокировки ACCESS EXCLUSIVE, которая ожидает блокировки ACCESS SHARE.
Длительные транзакции и изменения DDL требуют деликатной обработки.
person
zutnop
schedule
21.01.2021
base
, в любом случае, если мы никогда не собираемся менять таблицу? Если бы другой поток хотел изменить базовый DDL, ему обязательно потребовалась бы блокировка ACCESS EXCLUSIVE, и если бы текущий поток имел даже блокировку ACCESS SHARED наbase
, этого было бы достаточно, чтобы заблокировать это. Не могли бы вы уточнить, почему вы считаете, что замок необходим? - person Dave   schedule 22.08.2015