web-dev-qa-db-fra.com

Que se passe-t-il si deux processus tentent d'actualiser la vue matérialisée simultanément en même temps?

Selon les documents:

CONCURRENTLY Actualisez la vue matérialisée sans verrouiller les sélections simultanées sur la vue matérialisée. (...)

... AUTRES CONTENUS ...

Même avec cette option ne seule RAFRAÎCHISSEMENT à la fois peut fonctionner contre n'importe laquellene vue matérialisée.

I had une fonction qui vérifiait le dernier temps de rafraîchissement pour une VUE MATÉRIALISÉE et, si plus de 60 secondes s'étaient écoulées, elle le rafraîchirait.

Cependant, que se passerait-il si j'essayais d'actualiser une vue matérialisée à partir de deux processus distincts en même temps? feraient-ils la queue ou soulèveraient-ils une erreur?

Existe-t-il un moyen de détecter quand une VUE MATÉRIALISÉE est en cours de rafraîchissement et donc d'éviter de la toucher?

Actuellement, j'ai recouru à remplir un enregistrement de table avant d'actualiser (en définissant refreshing sur true), puis en le définissant sur false une fois le processus terminé.

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;

Ensuite, chaque fois que j'appelle cette procédure, je vérifie la plus récente last_update et sa valeur refreshing. Si refreshing est vrai, n'essayez pas de rafraîchir la vue matérialisée.

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;

Cependant, je ne suis pas sûr que l'indicateur d'actualisation soit mis à jour de manière synchrone (je veux dire, il attend vraiment que le rafraîchissement soit réellement terminé)

Cette approche est-elle rationnelle ou manque-t-il quelque chose ici?

13
ffflabs

Comme mentionné dans cette réponse , "REFRESH MATERIALIZED VIEW CONCURRENTLY prend un EXCLUSIVE lock "sur la table. En suivant le chemin des miettes vers documentation nous pouvons lire qu'un EXCLUSIVE lock sur une table" autorise uniquement les ACCESS SHARE les verrous, c'est-à-dire que seules les lectures de la table peuvent continuer ". Dans le même paragraphe, nous pouvons voir que" EXCLUSIVE entre en conflit avec ... EXCLUSIVE ", ce qui signifie qu'un autre REFRESH MATERIALIZED VIEW CONCURRENTLY, qui demande le même verrou EXCLUSIVE, devra attendre que le verrou EXCLUSIVE précédent soit libéré.

Si vous voulez éviter d'attendre ce verrou pendant une période indéfinie, vous pouvez définir la variable de session lock_timeout à une valeur sensible.

13
mustaccio

Comme indiqué par mustaccio , cette question chevauche de manière significative --- Postgres Refresh Materialized View Locks .

Cependant, alors que réponse acceptée à cette question a un lien qui répond à celle-ci, la réponse à cette question n'est pas directement incluse dans celle-ci.

Donc, pour être précis: selon la page de manuel de PostgreSQL sur le verrouillage explicite (le lien est vers la page de la version actuelle, pour PostGres 10), REFRESH MATERIALIZED VIEW CONCURRENTLY prend un verrou EXCLUSIVE. Le verrou EXCLUSIVE semble bloquer tous les autres verrous sauf ACCESS SHARE - qui inclut d'autres verrous EXCLUSIVE.

Donc une seconde REFRESH MATERIALIZED VIEW CONCURRENTLY la requête sur la même vue attendra que le verrou obtenu par le premier soit libéré.

3
RDFozz

Grâce aux réponses de mustaccio et RDFozz , j'ai finalement compris que REFRESH ... CONCURRENTLY la prise d'un verrou exclusif est la raison pour laquelle la documentation PostgreSQL indique :

Même avec cette option , une seule RAFRAÎCHISSEMENT à la fois peut s'exécuter contre n'importe quelle vue matérialisée .

J'avais peur que cela signifie que toute tentative de rafraîchissement simultané déclencherait une erreur , mais à la lumière de leurs réponses, il n'y a pas de erreur impliquée. C'est juste une question de verrous qui mettront en file d'attente les tentatives simultanées. Ainsi, la documentation pourrait plutôt être interprétée comme:

Le verrouillage acquis au cours de cette opération empêchera toute opération autre que la lecture de la VUE MATÉRIALISÉE. D'autres tentatives d'actualisation de la vue matérialisée pendant l'exécution de REFRESH ... CONCURRENTLY feront la queue jusqu'à ce que le premier verrou soit libéré.

0
ffflabs