Laut den Dokumenten:
KONZURRENT Aktualisieren Sie die materialisierte Ansicht, ohne gleichzeitige Auswahlen in der materialisierten Ansicht zu sperren. (...)
... ANDERE INHALTE ...
Selbst mit dieser Option kann jeweils nur ein REFRESH gegen eine materialisierte Ansicht ausgeführt werden .
Ich hatte eine Funktion, die die letzte Aktualisierungszeit für eine MATERIALISIERTE ANSICHT überprüfte, und wenn mehr als 60 Sekunden vergangen waren, würde sie aktualisiert.
Was würde jedoch passieren, wenn ich versuche, eine materialisierte Ansicht aus zwei getrennten Prozessen gleichzeitig zu aktualisieren? Würden sie sich anstellen oder einen Fehler auslösen?
Gibt es eine Möglichkeit zu erkennen, wann eine MATERIALISIERTE ANSICHT aktualisiert wird, und daher zu vermeiden, sie zu berühren?
Derzeit habe ich versucht, einen Tabellendatensatz zu füllen, bevor ich ihn aktualisiere ( refreshing
auf true
) und dann auf, false
wenn der Prozess abgeschlossen ist.
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;
Wenn ich diese Prozedur aufrufe, überprüfe ich dann die aktuellste last_update
und ihren refreshing
Wert. Wenn dies refreshing
zutrifft, versuchen Sie nicht, die materialisierte Ansicht zu aktualisieren.
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;
Ich bin mir jedoch nicht sicher, ob das Aktualisierungsflag synchron aktualisiert wird (ich meine, es wartet wirklich darauf, dass die Aktualisierung tatsächlich abgeschlossen ist).
Ist dieser Ansatz rational oder fehlt mir hier etwas?
quelle
pg_locks
um die Aktualisierung zu überprüfen und zu starten. Eine geeignete Methode zur Behebung von Sperrkonflikten besteht darin, ein Zeitlimit festzulegen und den Fehler zu behandeln.Wie von mustaccio festgestellt , überschneidet sich diese Frage erheblich mit Postgres Refresh Materialized View Locks .
Während die akzeptierte Antwort auf diese Frage einen Link enthält, der diese beantwortet, ist die Antwort auf diese Frage nicht direkt in dieser Antwort enthalten.
Also, um genau zu sein: Nach der PostgreSQL -Manpage auf explizite Sperren (Link ist auf die aktuelle Version Seite für PostGres 10),
REFRESH MATERIALIZED VIEW CONCURRENTLY
nimmt eineEXCLUSIVE
Sperre. DieEXCLUSIVE
Sperre scheint alle anderen Sperren zu blockieren, außerACCESS SHARE
- einschließlich andererEXCLUSIVE
Sperren.Eine zweite
REFRESH MATERIALIZED VIEW CONCURRENTLY
Anforderung in derselben Ansicht wartet also darauf, dass die von der ersten erhaltene Sperre freigegeben wird.quelle
Dank der Antworten von mustaccio und RDFozz habe ich endlich verstanden, dass
REFRESH ... CONCURRENTLY
die Verwendung einer exklusiven Sperre der Grund ist, aus dem die PostgreSQL-Dokumentation lautet :Ich befürchtete, dass dies bedeuten würde, dass jeder Versuch, eine gleichzeitige Aktualisierung durchzuführen, einen Fehler auslösen würde , aber angesichts ihrer Antworten gibt es keinen besonderen Fehler. Es ist nur eine Frage von Sperren, die gleichzeitige Versuche in die Warteschlange stellen. Die Dokumentation könnte also stattdessen wie folgt interpretiert werden:
quelle