Điều gì xảy ra nếu hai quá trình cố gắng TẠO LỰA CHỌN NGUYÊN LIỆU QUAN TRỌNG cùng một lúc?


13

Theo các tài liệu:

QUAN TRỌNG Làm mới chế độ xem cụ thể hóa mà không khóa các lựa chọn đồng thời trên chế độ xem cụ thể hóa. (...)

... NỘI DUNG KHÁC ...

Ngay cả với tùy chọn này, chỉ một REFRESH tại một thời điểm có thể chạy với bất kỳ chế độ xem cụ thể hóa nào .

Tôi đã có một chức năng kiểm tra thời gian làm mới lần cuối để XEM VẬT LIỆU và, nếu hơn 60 giây trôi qua, nó sẽ làm mới nó.

Tuy nhiên, điều gì sẽ xảy ra nếu tôi cố gắng làm mới một cái nhìn cụ thể hóa từ hai quy trình riêng biệt cùng một lúc? họ sẽ xếp hàng hay họ sẽ đưa ra một lỗi?

Có cách nào để phát hiện khi XEM XEM VẬT LIỆU đang được làm mới và do đó tránh chạm vào nó không?

Hiện tại, tôi đã dùng đến việc tạo một bản ghi bảng trước khi làm mới (cài đặt refreshingthành true) và sau đó thiết lập nó falsekhi quá trình kết thúc.

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;

Sau đó, bất cứ khi nào tôi gọi thủ tục này, tôi kiểm tra giá trị gần đây nhất last_updaterefreshinggiá trị của nó . Nếu refreshinglà đúng, thì đừng cố làm mới khung nhìn cụ thể hóa.

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;

Tuy nhiên, tôi không chắc chắn cờ làm mới đang được cập nhật đồng bộ (ý tôi là, nó thực sự chờ làm mới thực sự hoàn tất)

Cách tiếp cận này là hợp lý hay tôi đang thiếu một cái gì đó ở đây?

Câu trả lời:


13

Như đã đề cập trong câu trả lời này , " REFRESH MATERIALIZED VIEW CONCURRENTLYmất một EXCLUSIVEkhóa" trên bàn. Theo dấu vết vụn đến tài liệu, chúng ta có thể đọc rằng EXCLUSIVEkhóa trên bảng "chỉ cho phép ACCESS SHAREkhóa đồng thời , tức là chỉ đọc từ bảng mới có thể tiến hành". Trong cùng một đoạn chúng ta có thể thấy rằng " EXCLUSIVExung đột với ... EXCLUSIVE", có nghĩa là một REFRESH MATERIALIZED VIEW CONCURRENTLYtuyên bố khác , yêu cầu cùng một EXCLUSIVEkhóa, sẽ phải đợi cho đến khi EXCLUSIVEkhóa trước đó được phát hành.

Nếu bạn muốn tránh chờ khóa này trong một khoảng thời gian không xác định, bạn có thể muốn đặt biến phiênlock_timeout thành giá trị hợp lý.


Trả lời
ffflabs

Đó là vấn đề quan điểm; nếu bạn nghĩ rằng nó giúp bạn tất nhiên có thể giữ logic của bạn. Tuy nhiên, lưu ý rằng chức năng của bạn phải tuân theo các điều kiện chủng tộc và do đó không đáng tin cậy 100%.
mustaccio

Bạn có nghĩ rằng có thể kiểm tra pg_locks sau đó để xem liệu có ai tham chiếu chế độ xem mat không?
ffflabs

Một lần nữa, điều kiện cuộc đua có thể: có khả năng một khóa sẽ được đặt giữa bạn kiểm tra pg_locksvà bắt đầu làm mới. Một cách thích hợp để giải quyết xung đột khóa là đặt thời gian chờ và xử lý lỗi.
mustaccio

3

Như được ghi nhận bởi mustaccio , câu hỏi này trùng lặp đáng kể với Khóa chế độ xem được vật chất hóa của Postgres .

Tuy nhiên, trong khi câu trả lời được chấp nhận cho câu hỏi đó có một liên kết trả lời câu hỏi này, câu trả lời cho câu hỏi này không được bao gồm trực tiếp trong câu hỏi đó.

Vì vậy, để được cụ thể: Theo PostgreSQL trang hướng dẫn trên khóa rõ ràng (Link là trang phiên bản hiện tại, cho Postgres 10), REFRESH MATERIALIZED VIEW CONCURRENTLYphải mất một EXCLUSIVEkhóa. Các EXCLUSIVEkhóa xuất hiện để chặn tất cả ổ khóa khác trừ ACCESS SHARE - trong đó bao gồm khác EXCLUSIVEổ khóa.

Vì vậy, một REFRESH MATERIALIZED VIEW CONCURRENTLYyêu cầu thứ hai trên cùng một chế độ xem sẽ chờ khóa của cái đầu tiên được phát hành.


Cảm ơn bạn. Tôi vẫn đánh dấu câu trả lời của @ mustaccio là được chấp nhận kể từ khi anh ấy chỉnh sửa văn bản của mình để cụ thể hơn cho câu hỏi của tôi.
ffflabs

0

Nhờ các câu trả lời của mustaccioRDFozz , cuối cùng tôi đã hiểu rằng REFRESH ... CONCURRENTLYviệc lấy một khóa độc quyền là lý do mà tài liệu PostgreQuery nói :

Ngay cả với tùy chọn này, chỉ một REFRESH tại một thời điểm có thể chạy với bất kỳ chế độ xem cụ thể hóa nào .

Tôi sợ rằng điều này có nghĩa là bất kỳ nỗ lực nào để làm mới đồng thời sẽ gây ra lỗi , nhưng trong câu trả lời của họ, không có bất kỳ lỗi đặc biệt nào liên quan. Đó chỉ là vấn đề về khóa sẽ thu hút những nỗ lực đồng thời. Vì vậy, tài liệu thay vào đó có thể được hiểu là:

Khóa có được trong quá trình thao tác này sẽ ngăn mọi thao tác khác ngoài việc đọc từ XEM TÀI LIỆU. Những nỗ lực tiếp theo để làm mới Chế độ xem được vật chất hóa trong khi LẠNH ... TUYỆT VỜI đang chạy sẽ xếp hàng cho đến khi khóa đầu tiên được phát hành.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.