Według dokumentów:
OBECNIE Odśwież widok zmaterializowany bez blokowania współbieżnych zaznaczeń w widoku zmaterializowanym. (...)
... INNE TREŚCI ...
Nawet z tą opcją tylko jeden ODŚWIEŻANIE może działać jednocześnie z dowolnym zmaterializowanym widokiem .
I miał funkcję sprawdzenia ostatniego czasu odświeżania na zmaterializował widzenia, a jeśli więcej niż 60 sekund minęło, że będzie się ją odświeżyć.
Co by się jednak stało, gdybym spróbował odświeżyć zmaterializowany widok z dwóch oddzielnych procesów jednocześnie? czy staną w kolejce, czy zgłoszą błąd?
Czy istnieje sposób na wykrycie, kiedy WIDOK MATERIALIZOWANY jest odświeżany, i dlatego należy go unikać?
Obecnie postanowiłem wypełnić rekord tabeli przed odświeżeniem (ustawieniem refreshing
na true
), a następnie ustawieniem go na false
zakończenie procesu.
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;
Następnie za każdym razem, gdy wywołuję tę procedurę, sprawdzam najnowszą last_update
i jej refreshing
wartość. Jeśli refreshing
jest to prawda, nie próbuj odświeżać zmaterializowanego widoku.
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;
Nie jestem jednak pewien, czy flaga odświeżania jest aktualizowana synchronicznie (to znaczy naprawdę czeka na zakończenie odświeżania)
Czy to podejście jest racjonalne, czy coś mi brakuje?
źródło
pg_locks
a zaczniesz odświeżanie. Właściwym sposobem na rozwiązanie konfliktu blokady jest ustawienie limitu czasu i obsłużenie błędu.Jak zauważył mustaccio , pytanie to pokrywa się znacznie z Postgres Refresh Materialized View Locks .
Jednak chociaż zaakceptowana odpowiedź na to pytanie zawiera link, który odpowiada na to pytanie, odpowiedź na to pytanie nie jest bezpośrednio zawarta w tym.
Tak, za szczególne: Zgodnie z ręcznym stronie PostgreSQL na wyraźną blokadą (Link jest do aktualnej wersji strony, dla PostgreSQL 10),
REFRESH MATERIALIZED VIEW CONCURRENTLY
zajmujeEXCLUSIVE
zamek.EXCLUSIVE
Zamek wydaje się blokować wszystkie inne zamki z wyjątkiemACCESS SHARE
- który obejmuje inneEXCLUSIVE
zamki.Tak więc drugie
REFRESH MATERIALIZED VIEW CONCURRENTLY
żądanie w tym samym widoku będzie czekać na zwolnienie blokady uzyskanej przez pierwszą.źródło
Dzięki odpowiedziom Mustaccio i RDFozz w końcu zrozumiałem, że
REFRESH ... CONCURRENTLY
podjęcie wyłącznej blokady jest powodem, dla którego dokumentacja PostgreSQL mówi :Obawiałem się, że oznacza to, że każda próba jednoczesnego odświeżenia spowoduje błąd , ale w świetle ich odpowiedzi nie ma żadnego specjalnego błędu. To tylko kwestia zamków, które będą kolejkować jednoczesne próby. Dokumentację można więc interpretować jako:
źródło