De acordo com os documentos:
Atualize CONCORRENTE a vista materializada sem bloquear as opções simultâneas na vista materializada. (...)
... OUTROS CONTEÚDOS ...
Mesmo com essa opção, apenas uma atualização por vez pode ser executada em qualquer visualização materializada .
Eu tinha uma função que verificava o último tempo de atualização para uma VISÃO MATERIALIZADA e, se tivessem passado mais de 60 segundos, seria necessário atualizá-la.
No entanto, o que aconteceria se eu tentasse atualizar uma exibição materializada de dois processos separados ao mesmo tempo? eles colocariam na fila ou gerariam um erro?
Existe uma maneira de detectar quando uma VISTA MATERIALIZADA está sendo atualizada e, portanto, evitar tocá-la?
Atualmente, recorri ao preenchimento de um registro da tabela antes de atualizar (configurando refreshing
para true
) e depois defini-lo para false
quando o processo terminar.
EXECUTE 'INSERT INTO refresh_status (last_update, refreshing)
VALUES (clock_timestamp(), true) RETURNING id') INTO refresh_id;
EXECUTE 'REFRESH MATERIALIZED VIEW CONCURRENTLY my_mat_view';
EXECUTE 'UPDATE refresh_status SET refreshing=false WHERE id=$1' USING refresh_id;
Então, sempre que chamo esse procedimento, verifico o mais recente last_update
e seu refreshing
valor. Se refreshing
for verdade, não tente atualizar a exibição materializada.
EXECUTE 'SELECT
extract(epoch FROM now() - (last_update))::integer,
refreshing
FROM refresh_status
ORDER BY last_update DESC
LIMIT 1' INTO update_seconds_ago, refreshing;
IF(updated_seconds_ago > 60 AND refreshing = FALSE) THEN
-- the refresh block above
END IF;
No entanto, não tenho certeza se o sinalizador de atualização está sendo atualizado de forma síncrona (quero dizer, ele realmente aguarda a atualização ser concluída)
Essa abordagem é racional ou estou perdendo alguma coisa aqui?
fonte
pg_locks
e iniciar a atualização. Uma maneira adequada de resolver conflitos de bloqueio é definir o tempo limite e manipular o erro.Conforme observado pelo mustaccio , essa pergunta se sobrepõe significativamente aos Bloqueios de exibição materializados de atualização do Postgres .
No entanto, embora a resposta aceita para essa pergunta tenha um link que responda a essa pergunta, a resposta a essa pergunta não está diretamente incluída nessa.
Portanto, para ser específico: de acordo com a página de manual do PostgreSQL sobre bloqueio explícito (o link é para a página da versão atual, para o PostGres 10),
REFRESH MATERIALIZED VIEW CONCURRENTLY
aceita umEXCLUSIVE
bloqueio. OEXCLUSIVE
bloqueio parece bloquear todos os outros bloqueios, excetoACCESS SHARE
- isso inclui outrosEXCLUSIVE
bloqueios.Portanto, uma segunda
REFRESH MATERIALIZED VIEW CONCURRENTLY
solicitação na mesma exibição aguardará a liberação do bloqueio obtido pelo primeiro.fonte
Graças às respostas de mustaccio e RDFozz , finalmente entendi que
REFRESH ... CONCURRENTLY
usar um bloqueio exclusivo é a razão pela qual a documentação do PostgreSQL diz :Eu tinha medo de que isso significasse que qualquer tentativa de fazer uma atualização simultânea geraria um erro , mas, à luz de suas respostas, não há nenhum erro especial envolvido. É apenas uma questão de bloqueios que enfileiram tentativas simultâneas. Portanto, a documentação poderia ser interpretada como:
fonte