Các tùy chọn của bạn là:
-
Chạy trong
SERIALIZABLEsự cách ly. Các giao dịch phụ thuộc lẫn nhau sẽ bị hủy bỏ khi cam kết gặp lỗi tuần tự hóa. Bạn sẽ nhận được rất nhiều thư rác nhật ký lỗi và bạn sẽ phải thử lại nhiều lần, nhưng nó sẽ hoạt động một cách đáng tin cậy. -
Xác định một
UNIQUEràng buộc và thử lại khi không thành công, như bạn đã lưu ý. Các vấn đề tương tự như trên. -
Nếu có một đối tượng chính, bạn có thể
SELECT ... FOR UPDATEđối tượng chính trước khi thực hiệnmaxcủa bạn truy vấn. Trong trường hợp này, bạnSELECT 1 FROM bar WHERE bar_id = $1 FOR UPDATE. Bạn đang sử dụngbarlàm khóa cho tất cảfoos vớibar_idđó . Sau đó, bạn có thể biết rằng có thể tiếp tục an toàn, miễn là mọi truy vấn đang thực hiện tăng bộ đếm của bạn đều thực hiện điều này một cách đáng tin cậy. Điều này có thể hoạt động khá tốt.Điều này vẫn thực hiện một truy vấn tổng hợp cho mỗi cuộc gọi, điều này (cho mỗi tùy chọn tiếp theo) là không cần thiết, nhưng ít nhất nó không spam nhật ký lỗi như các tùy chọn trên.
-
Sử dụng bàn truy cập. Đây là những gì tôi muốn làm. Trong
barhoặc trong bảng phụ nhưbar_foo_counter, có được ID hàng bằng cách sử dụngUPDATE bar_foo_counter SET counter = counter + 1 WHERE bar_id = $1 RETURNING counterhoặc tùy chọn kém hiệu quả hơn nếu khung của bạn không thể xử lý
RETURNING:SELECT counter FROM bar_foo_counter WHERE bar_id = $1 FOR UPDATE; UPDATE bar_foo_counter SET counter = $1;Sau đó, trong cùng một giao dịch , sử dụng hàng bộ đếm đã tạo cho
number. Khi bạn cam kết, dòng bảng bộ đếm chobar_idđó được mở khóa cho truy vấn tiếp theo để sử dụng. Nếu bạn quay lại, thay đổi sẽ bị hủy.
Tôi đề xuất phương pháp tiếp cận bộ đếm, sử dụng bảng phụ dành riêng cho bộ đếm thay vì thêm cột vào bar . Điều đó rõ ràng hơn để tạo mô hình và có nghĩa là bạn tạo ít khối cập nhật hơn trong bar , điều này có thể làm chậm các truy vấn đến bar .