두 프로세스가 동시에 머 시리얼 뷰를 새로 고치려고하면 어떻게됩니까?


13

문서에 따르면 :

구체화 된 뷰에서 동시 선택을 잠그지 않고 구체화 된 뷰를 새로 고칩니다. (...)

... 다른 내용 ...

이 옵션을 사용하더라도 한 번에 하나의 REFRESH 만 하나의 구체화 된보기 에 대해 실행될 수 있습니다 .

나는 했다 구체화 된보기의 마지막 새로 고침 시간을 확인하는 기능을하고 60 초 이상 경과 한 경우, 그것을 새로 고치려면 것.

그러나 두 개의 개별 프로세스에서 구체화 된 뷰를 동시에 새로 고치려고하면 어떻게됩니까? 대기열에 넣거나 오류가 발생합니까?

MATERIALIZED VIEW가 새로 고쳐지는시기를 감지하여 만지지 않도록하는 방법이 있습니까?

현재, 나는 (설정 상쾌한 전에 테이블 레코드를 채울 의지 한 refreshingtrue) 다음으로 설정 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값을 확인합니다 . refreshingtrue 인 경우 구체화 된보기를 새로 고치려고하지 마십시오.

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;

그러나 새로 고침 플래그가 동 기적으로 업데이트되고 있는지 확실하지 않습니다 (새로 고침이 실제로 새로 고침이 끝날 때까지 기다립니다)

이 접근법이 합리적입니까, 아니면 여기에 뭔가 빠졌습니까?

답변:


13

에서 언급 한 바와 같이 이 대답 , " REFRESH MATERIALIZED VIEW CONCURRENTLY소요 EXCLUSIVE테이블에 잠금을". 바스라기 흔적을 문서화EXCLUSIVE 한 후 테이블에 대한 잠금은 "동시 ACCESS SHARE잠금 만 허용합니다 . 즉, 테이블에서 읽기만 진행할 수 있습니다"를 읽을 수 있습니다. 같은 단락에서 " EXCLUSIVE...과 충돌합니다. EXCLUSIVE" REFRESH MATERIALIZED VIEW CONCURRENTLY는 동일한 EXCLUSIVE잠금 을 요청 하는 다른 명령문 이 이전 EXCLUSIVE잠금이 해제 될 때까지 기다려야 함을 의미합니다 .

정의되지 않은 기간 동안이 잠금을 기다리지 않으려면 세션 변수lock_timeout 를 적절한 값 으로 설정하십시오 .


추신 :이 보조 테이블을 유지하여 MAT VIEW가 사용 중이므로 새로 고침이 필요한 것처럼 보이더라도 혼자 두어야한다고 시도하는 것이 좋습니다.
fffs

그것은 의견의 문제입니다. 그것이 논리를 유지하는 데 도움이된다고 생각한다면. 그러나 귀하의 기능은 경쟁 조건의 영향을 받으므로 100 % 신뢰할 수는 없습니다.
mustaccio

pg_locks를 확인한 다음 매트 뷰를 참조하는 것이 있는지 확인할 수 있습니까?
fffs

다시 한 번, 경쟁 조건이 가능합니다. 확인 pg_locks후 새로 고침을 시작하기 전에 잠금이 설정 될 수 있습니다 . 잠금 충돌을 해결하는 올바른 방법은 시간 초과를 설정하고 오류를 처리하는 것입니다.
mustaccio

3

mustaccio가 언급 했듯이이 질문은 Postgres Refresh Materialized View Locks 와 크게 겹 칩니다 .

그동안 단, 허용 대답은 그 질문이 하나를 응답하는 링크가이 질문에 대한 대답은 바로 하나에 포함되지 않습니다.

그럼, 구체적으로 다음에 따라 명시 적으로 잠금에 PostgreSQL의 매뉴얼 페이지 (링크는 포스트 그레스를 들어, 현재 버전 페이지 10), REFRESH MATERIALIZED VIEW CONCURRENTLY소요 EXCLUSIVE잠금을. EXCLUSIVE잠금은 다른 모든 잠금을 차단하는 표시 를 제외하고 ACCESS SHARE 다른 포함하는 - EXCLUSIVE잠금.

따라서 REFRESH MATERIALIZED VIEW CONCURRENTLY동일한 뷰에 대한 두 번째 요청 은 첫 번째 요청에서 얻은 잠금이 해제 될 때까지 기다립니다.


감사합니다. 나는 내 질문에 더 구체적으로 텍스트를 편집했기 때문에 여전히 @mustaccio의 대답을 수락 된 것으로 표시했습니다.
fffs

0

mustaccioRDFozz 의 답변 덕분에 마침내 REFRESH ... CONCURRENTLY독점 잠금 을 취하는 것이 PostgreSQL 문서가 말하는 이유 임을 이해했습니다 .

이 옵션을 사용하더라도 한 번에 하나의 REFRESH 만 하나의 구체화 된보기 에 대해 실행될 수 있습니다 .

이것은 동시 새로 고침을 시도 하면 오류가 발생 한다는 것을 두려워 했지만 답변에 비추어 볼 때 특별한 오류는 없습니다. 동시 시도를 대기시키는 잠금 문제 일뿐입니다. 따라서 설명서는 다음과 같이 해석 될 수 있습니다.

이 작업 중에 획득 한 잠금 장치는 MATERIALIZED VIEW에서 읽는 것 이외의 작업을 방지합니다. REFRESH ... CONCURRENTLY가 실행되는 동안 구체화 된 뷰를 새로 고치려고 시도하면 첫 번째 잠금이 해제 될 때까지 대기합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.