Esta é uma continuação da minha pergunta antiga Múltiplas "REFRESH MATERIALIZED VIEW" simultâneas: como gerenciar?
Agora, infelizmente, estou lutando com a coisa real depois de ter sido mais teórico inicialmente :)
Eu tenho um programa que envia muitas solicitações e, finalmente, atualiza uma visão materializada. Infelizmente, às vezes, dois jobs simultâneos solicitam sobreposição CREATE MATERIALIZED VIEW milestones_files
(a visualização é muito grande e leva vários minutos para ser atualizada), então o último falha (obviamente), o que cancela toda a transação (o que é ruim, porque algumas atualizações do banco de dados também são descartadas ).
Aqui está o log quando o erro ocorre (sem todas as linhas SQL para abreviar):
2022-03-22 11:17:37.685 UTC [29004] storiq@storiqone ERREUR: Bloquage mortel détecté
2022-03-22 11:17:37.685 UTC [29004] storiq@storiqone DÉTAIL: Le processus 29004 attend AccessExclusiveLock sur relation 181019 de la base de données 19044 ; bloqué par le processus 29174.
2022-03-22 11:17:37.685 UTC [29004] storiq@storiqone ASTUCE : Voir les journaux applicatifs du serveur pour les détails sur la requête.
2022-03-22 11:17:37.685 UTC [29004] storiq@storiqone INSTRUCTION : CREATE MATERIALIZED VIEW milestones_files_29000 AS SELECT sa.id AS archive,
2022-03-22 11:17:37.691 UTC [29243] storiq@storiqone ERREUR: could not open relation with OID 181019
2022-03-22 11:17:37.691 UTC [29243] storiq@storiqone INSTRUCTION : SELECT REGEXP_REPLACE(pg_catalog.pg_get_ruledef(r.oid, TRUE), '^.*DO INSTEAD (SELECT.*);$', '\1') FROM pg_catalog.pg_rewrite r WHERE r.ev_class = ( SELECT oid FROM pg_class WHERE relname = 'milestones_files')
2022-03-22 11:17:37.693 UTC [29243] storiq@storiqone ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
2022-03-22 11:17:37.693 UTC [29243] storiq@storiqone INSTRUCTION : UPDATE archivetoarchivemirror SET lastupdate = NOW(), jobrun = $1 WHERE archive = $2 OR jobrun = $1
2022-03-22 11:17:37.696 UTC [29243] storiq@storiqone ERREUR: l'instruction préparée « update_archivemirrors » n'existe pas
2022-03-22 11:17:39.510 UTC [29004] storiq@storiqone ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc
2022-03-22 11:17:39.510 UTC [29004] storiq@storiqone INSTRUCTION : UPDATE archivetoarchivemirror SET lastupdate = NOW(), jobrun = $1 WHERE archive = $2 OR jobrun = $1
2022-03-22 11:17:39.510 UTC [29004] storiq@storiqone ERREUR: l'instruction préparée « update_archivemirrors » n'existe pas
É claro que eu poderia simplesmente colocar o CREATE MATERIALIZED VIEW
comando fora da transação principal, no entanto, a atualização mais recente ainda falharia, portanto, a exibição não refletiria as últimas alterações no banco de dados, o que ainda é um problema (menos sério).
Idealmente, eu gostaria que a atualização mais recente tivesse precedência, mas sem falhar na transação já em execução no outro processo (o que seria o caso se eu simplesmente matasse o outro processo após a verificação de bloqueios, conforme Kill concorrente materialized view refresh PID ) .
A partir da documentação, não parece que adicionar a CONCURRENTLY
opção também resolveria meu problema (que não é sobre SELECTs simultâneos).
Qualquer sugestão bem vinda. É claro que eu poderia tentar implementar a solução proposta na minha pergunta antiga, embora fosse particularmente complexa, dadas as consultas e transações em cascata e o enorme banco de dados ...
Você poderia escrever um procedimento para isso:
O mesmo também pode ser escrito usando o código do cliente. Isso pode travar, mas nunca travar, e você pode ter certeza de que a visualização materializada refletirá as inserções quando o procedimento for concluído.