Para qualquer pessoa pesquisando e tentando entender por que sua tabela de descarte (ou descarte de chave estrangeira ou adicione chave estrangeira) ficou presa por um longo tempo:
PostgreSQL (Eu olhei para as versões 9.4 a 13) as restrições de chave estrangeira são realmente implementadas usando gatilhos em ambas as extremidades da chave estrangeira .
Se você tiver uma tabela de empresa (id como chave primária) e uma tabela bank_account (id como chave primária, company_id como chave estrangeira apontando para company.id), na verdade existem 2 gatilhos na tabela bank_account e também 2 gatilhos na empresa tabela.
table_name | tempo | trigger_name | function_name |
---|---|---|---|
conta_bancária | APÓS ATUALIZAÇÃO | RI_ConstraintTrigger_c_1515961 | RI_FKey_check_upd |
conta_bancária | APÓS INSERIR | RI_ConstraintTrigger_c_1515960 | RI_FKey_check_ins |
empresa | APÓS ATUALIZAÇÃO | RI_ConstraintTrigger_a_1515959 | RI_FKey_noaction_upd |
empresa | APÓS A EXCLUSÃO | RI_ConstraintTrigger_a_1515958 | RI_FKey_noaction_del |
A criação inicial desses gatilhos (ao criar a chave estrangeira) requer o bloqueio SHARE ROW EXCLUSIVE nessas tabelas (costumava ser o bloqueio ACCESS EXCLUSIVE na versão 9.4 e anteriores). Este bloqueio não entra em conflito com "bloqueios de leitura de dados", mas entrará em conflito com todos os outros bloqueios, por exemplo, um simples INSERT/UPDATE/DELETE na tabela da empresa.
A exclusão desses gatilhos (ao descartar a chave estrangeira ou a tabela inteira) requer o bloqueio ACCESS EXCLUSIVE nessas tabelas. Este bloqueio entra em conflito com todos os outros bloqueios!
Então imagine um cenário, onde você tem uma transação A em execução que primeiro fez um simples SELECT da tabela da empresa (fazendo com que ele mantenha um bloqueio ACCESS SHARE para a tabela da empresa até que a transação seja confirmada ou revertida) e agora está fazendo algum outro trabalho para 3 minutos. Você tenta descartar a tabela bank_account na transação B. Isso requer o bloqueio ACCESS EXCLUSIVE, que precisará aguardar até que o bloqueio ACCESS SHARE seja liberado primeiro. ou talvez INSERT/UPDATE/DELETE), será enfileirado para aguardar o bloqueio ACCESS EXCLUSIVE, que está aguardando o bloqueio ACCESS SHARE.
Transações de longa duração e alterações de DDL requerem manuseio delicado.