PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Evite bloqueios de acesso exclusivos em tabelas referenciadas ao DROPping no PostgreSQL


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.