Согласно документам:
В то же время Обновите материализованное представление, не блокируя параллельные выборки в материализованном представлении. (...)
... ДРУГОЕ СОДЕРЖАНИЕ ...
Даже с этой опцией только один REFRESH одновременно может работать с любым материализованным представлением .
У меня была функция, которая проверяла время последнего обновления для МАТЕРИАЛИЗИРОВАННОГО ВИДА и, если прошло более 60 секунд, оно обновило бы его.
Однако что произойдет, если я попытаюсь обновить материализованное представление из двух отдельных процессов одновременно? Будут ли они в очереди или они вызовут ошибку?
Есть ли способ определить, когда обновляется МАТЕРИАЛИЗИРОВАННЫЙ ВИД, и, следовательно, избегать его касания?
В настоящее время я прибегал , чтобы заполнить запись таблицы перед обновлением (настройка refreshing
в true
) , а затем установить его в , false
когда процесс завершен.
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;
Затем, всякий раз, когда я вызываю эту процедуру, я проверяю самое последнее last_update
и его refreshing
значение. Если refreshing
это правда, то не пытайтесь обновить материализованное представление.
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;
Тем не менее, я не уверен, что флаг обновления обновляется синхронно (я имею в виду, что он действительно ожидает завершения обновления)
Это рациональный подход или я что-то здесь упускаю?
источник
pg_locks
и начнется обновление. Правильный способ устранения конфликтов блокировки - установить таймаут и обработать ошибку.Как отметил Мустаччо , этот вопрос значительно совпадает с блокировками представлений Postgres Refresh .
Однако, хотя принятый ответ на этот вопрос имеет ссылку, которая отвечает на этот вопрос, ответ на этот вопрос напрямую не включен в этот вопрос.
Итак, чтобы быть конкретным: согласно странице руководства PostgreSQL по явной блокировке (ссылка на страницу текущей версии, для PostGres 10),
REFRESH MATERIALIZED VIEW CONCURRENTLY
принимаетEXCLUSIVE
блокировку.EXCLUSIVE
Замок , кажется, блокирует все другие замки , за исключениемACCESS SHARE
- что включает в себя другиеEXCLUSIVE
замки.Таким образом, второй
REFRESH MATERIALIZED VIEW CONCURRENTLY
запрос в том же представлении будет ожидать блокировки, полученной первым, для освобождения.источник
Благодаря ответам mustaccio и RDFozz я наконец понял, что
REFRESH ... CONCURRENTLY
взятие эксклюзивной блокировки является причиной, по которой в документации PostgreSQL говорится :Я боялся, что это означает, что любая попытка одновременного обновления приведет к ошибке , но в свете их ответов особой ошибки не возникает. Это просто вопрос замков, которые ставят в очередь одновременные попытки. Таким образом, документация может быть интерпретирована как:
источник