postgresql 9.5 - заблокировать дочернее материализованное представление, пока родители обновляются одновременно

У меня есть материализованное представление, которое зависит от нескольких других материализованных представлений.

matviewA matviewB matviewC
    \       |       /
         matviewX

Я бы хотел обновить родительские материализованные представления одновременно все одновременно. (На самом деле это не проблема - как показано ниже.) [В моей текущей среде обновление каждого родителя занимает около часа. ]

psql -c "refresh materialized view concurrently matviewA" &
psql -c "refresh materialized view concurrently matviewB" &
psql -c "refresh materialized view concurrently matviewC" &

Однако, если я начну обновление для ребенка:

psql -c "refresh materialized view concurrently matviewX" &

Он запускается сразу и не ждет, пока родители закончат обновление, потому что они не запрещают своим детям выполнять обновления, в то время как они сами уже обновляются одновременно.

Я попытался заблокировать ребенка, пока родители бегают:

psql -c "lock matviewX in share mode; refresh materialized view concurrently matviewA" &
psql -c "lock matviewX in share mode; refresh materialized view concurrently matviewB" &
psql -c "lock matviewX in share mode; refresh materialized view concurrently matviewC" &

К сожалению, вы не можете явно заблокировать материализованные представления.

Если я не использую «одновременно» для родителей, дочернее материализованное представление станет нечитаемым. (Но дочернее обновление ждет перед запуском.)

Я могу написать управление блокировками в сценарии оболочки (bash), который вызывает «psql -c». Или я мог бы использовать более сложный сторонний планировщик заданий. Я надеялся, что будет более простой способ.

Я мог бы написать функцию и поместить все обновления в эту функцию, а затем использовать временную таблицу для ручного явного управления блокировками.

Или, может быть, как-нибудь использовать рекомендательные блокировки.

Предложения?


person rotten    schedule 06.07.2016    source источник


Ответы (1)


Вы можете просто использовать wait (см. https://stackoverflow.com/a/18663969/3886053):

for parent in matviewA matviewB matviewC; do
  psql -c "refresh materialized view concurrently $parent" &
  echo "Started refreshing materialized view $parent"
done
echo -n "Waiting for all parents to finish... "
wait
echo "finished. Refreshing now the child materialized view"
psql -c "refresh materialized view concurrently matviewX"
person Ezequiel Tolnay    schedule 07.07.2016