Postgres, MVCC và Khóa


8

Tôi có một loạt các câu lệnh SQL trông giống như sau:

BEGIN;
SELECT counter FROM table WHERE id=X FOR UPDATE;
REALLY COMPLEX QUERY;
UPDATE table SET counter=Y WHERE id=X;
END;

Tôi muốn ngăn không cho bộ đếm được đọc trong khi tôi tính lại giá trị của nó, nhưng theo tài liệu của Postgres "Khóa cấp hàng không ảnh hưởng đến truy vấn dữ liệu; chúng chỉ chặn các nhà văn vào cùng một hàng."

Câu hỏi:

  1. Điểm của khóa hàng "ngoại lệ" là gì nếu nó không ngăn được đọc? Có phải chỉ để ngăn chặn các giao dịch khác lấy khóa chia sẻ?
  2. Nếu tôi đọc hàng với CHỌN ... ĐỂ CHIA SẺ, điều đó có đạt được ảnh hưởng tương tự như khóa "ngoại lệ" không?
  3. Có thể tắt MVCC cho bảng / lược đồ / cơ sở dữ liệu và cho phép ghi tại chỗ không?

Câu trả lời:


5

đến 1) Bất kỳ phiên nào khác sẽ đọc dữ liệu được sửa đổi bởi giao dịch của bạn như trước tuyên bố "BEGIN" của bạn miễn là giao dịch của bạn không cam kết. Ngay sau khi giao dịch của bạn được cam kết, nó sẽ đọc giá trị mới của quầy. Vấn đề là những người khác không phải chờ đợi và sẽ luôn thấy một cơ sở dữ liệu nhất quán.

đến 2), 3) Tại sao bạn không thử với "ĐỘC QUYỀN TIẾP CẬN"? (xem http://www.postgresql.org/docs/civerse/static/explicit-locking.html )

CHỈNH SỬA: Nếu bạn không thích khóa toàn bộ bảng bằng khóa "ACCESS EXCLUSIVE", bạn cũng có thể sử dụng "Khóa tư vấn" (xem phần 13.3.4 trong liên kết ở trên).


1

Nếu các lần đọc bạn muốn chặn là các lần thực hiện đồng thời của cùng một giao dịch chỉ với các dữ liệu khác nhau, hãy sử dụng câu lệnh CẬP NHẬT với mệnh đề trả về.

Kiểm tra tài liệu về tuyên bố CẬP NHẬT. Để trả lời câu hỏi của bạn về điểm khóa hàng độc quyền, đó là ngăn chặn sự không thống nhất dữ liệu từ các cập nhật đồng thời. Người đọc có được một cái nhìn nhất quán về cơ sở dữ liệu mọi lúc.


1

Trong mẫu mã bạn đã cung cấp, tất cả các lần đọc của hàng đó sẽ thấy giá trị cũ cho đến khi giao dịch đó được thực hiện.

1) Xem xét mẫu mã được chạy hai lần đồng thời, với cùng giá trị là X. Nếu cá thể A đã chạy select ... for updatethì nó đã khóa hàng đó cho đến khi nó bắt đầu. Trường hợp B, làm tương tự, sẽ ngăn chặn việc cố gắng khóa theo cùng một cách. Chỉ khi A cam kết, B mới có thể tiếp tục. B sau đó sẽ nhận được giá trị A bị bỏ lại trong bản cập nhật cuối cùng của nó.

Nếu Yphụ thuộc vào giá trị mà select ... for updatetruy vấn đọc hoặc giá trị khác của truy vấn trong phần 'phức tạp', thì điều này sẽ có tác dụng tương tự như khi chúng được chạy một cách an toàn - bạn không nhận được điều kiện cuộc đua trong đó một trong các kết quả sẽ là bỏ đi.

Nếu Yhoàn toàn là kết quả của các truy vấn phức tạp ở giữa, thì việc chạy song song mà không có select ... for updatecả hai sẽ thực hiện cùng một bản cập nhật.

2) for sharesẽ cho phép các lựa chọn khác trên hàng đó được tiến hành, nhưng sẽ khiến mọi thứ khác cố gắng select ... for updatehoặc update ...chặn cho đến khi hoàn thành. Nếu mã mẫu được chạy hai lần, đồng thời, chúng sẽ bế tắc trong việc tiếp cận updatecâu lệnh, khiến một trong số chúng bị hủy bỏ.

3) Không. Làm điều này rất nguy hiểm, vì người đọc có thể đọc một trường được cập nhật một nửa. (Hoặc đọc phần còn lại của một trường được cập nhật sau khi bắt đầu đọc.) Nó cũng có thể phá vỡ tính nhất quán, hiển thị cho người đọc một giá trị được cập nhật sau khi bắt đầu giao dịch.

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.