Según los documentos:
CONCURRENTEMENTE Actualizar la vista materializada sin bloquear selecciones concurrentes en la vista materializada. (...)
... OTROS CONTENIDOS ...
Incluso con esta opción, solo un REFRESH a la vez puede ejecutarse contra cualquier vista materializada .
Yo tenía una función que comprueba el último tiempo de actualización de una vista materializada y, si habían pasado más de 60 segundos, sería para actualizarlo.
Sin embargo, ¿qué sucedería si trato de actualizar una vista materializada de dos procesos separados al mismo tiempo? ¿harían cola o generarían un error?
¿Hay alguna forma de detectar cuándo se actualiza una VISTA MATERIALIZADA y, por lo tanto, evitar tocarla?
Actualmente, he recurrido a rellenar un registro de tabla antes de actualizar (establecer refreshing
en true
) y luego configurarlo false
cuando el proceso haya finalizado.
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;
Luego, cada vez que llamo a este procedimiento, verifico el más reciente last_update
y su refreshing
valor. Si refreshing
es cierto, no intente actualizar la vista 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;
Sin embargo, no estoy seguro de que el indicador de actualización se actualice sincrónicamente (es decir, realmente espera a que la actualización se complete)
¿Es este enfoque racional o me falta algo aquí?
fuente
pg_locks
y el inicio de la actualización. Una forma adecuada de abordar los conflictos de bloqueo es establecer el tiempo de espera y manejar el error.Como señaló Mustaccio , esta pregunta se superpone significativamente con los bloqueos de vista materializada de actualización de Postgres .
Sin embargo, aunque la respuesta aceptada a esa pregunta tiene un enlace que responde a esta, la respuesta a esta pregunta no se incluye directamente en esa.
Entonces, para ser específicos: de acuerdo con la página del manual de PostgreSQL sobre bloqueo explícito (el enlace es a la página de la versión actual, para PostGres 10),
REFRESH MATERIALIZED VIEW CONCURRENTLY
seEXCLUSIVE
bloquea. ElEXCLUSIVE
bloqueo parece bloquear todos los demás bloqueos, exceptoACCESS SHARE
que incluye otrosEXCLUSIVE
bloqueos.Por lo tanto, una segunda
REFRESH MATERIALIZED VIEW CONCURRENTLY
solicitud en la misma vista esperará a que se libere el bloqueo obtenido por el primero.fuente
Gracias a las respuestas de mustaccio y RDFozz , finalmente entendí que
REFRESH ... CONCURRENTLY
tomar un bloqueo exclusivo es la razón por la cual la documentación de PostgreSQL dice :Tenía miedo de que esto significara que cualquier intento de hacer una actualización simultánea arrojaría un error , pero a la luz de sus respuestas, no hay ningún error especial involucrado. Es solo una cuestión de cerraduras que provocarán intentos simultáneos. Por lo tanto, la documentación podría interpretarse como:
fuente