Tôi là người mới đến Postgres và yêu thích nó cho đến nay. Tôi đã đưa ra vấn đề này rất nhiều suy nghĩ, RTFM với khả năng tốt nhất của tôi, nhưng nhấn vào một kết thúc chết, vì vậy tôi cần một cú huých đi đúng hướng.Thực hiện cập nhật khách hàng gia tăng với hàng ngang trong Postgres
Tôi đang thiết kế cơ sở dữ liệu trong đó mỗi pháp nhân quan tâm có cột rowversion
được chỉ định giá trị từ chuỗi toàn cầu. Vì vậy, trong kịch bản đơn giản nhất, trong một bảng emps
với hai hàng: emp1
với [email protected]
và emp2
với [email protected]
, tôi biết emp2
đã được sửa đổi sau khi emp1
(tức là trong một giao dịch sau này - không thực sự quan tâm nếu hàng trong cùng một giao dịch có giống nhau rowversion
).
Điều này tạo thành nền tảng của logic đồng bộ hóa dữ liệu, nơi khách hàng biết rằng họ có mọi thứ cho đến @ 3, có thể nhận các bản cập nhật mới nhất bằng truy vấn như SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor
.
Dưới đây là một kịch bản ví dụ cho một khách hàng đã được cập nhật @ 3 - giả định giao dịch chủ yếu từ:
@3 - committed
@4 - committed
@5 - committed
@6 - in progress - not committed yet
@7 - committed
@8 - in progress - not committed yet
@9 - committed
khách hàng cập nhật được thực hiện trong ba giai đoạn:
- Ask cơ sở dữ liệu cho một thích hợp
new_anchor
. - Thực hiện
SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor
. - Chuyển giá trị
new_anchor
về cho khách hàng cùng với dữ liệu kết quả.
Kể từ khi hàng với rowversion
@ 6 và @ 8 vẫn đang được tiến hành, new_anchor
phải là @ 5, để truy vấn phạm vi của chúng tôi không bỏ lỡ bất kỳ bản cập nhật không bị giam. Bây giờ khách hàng có thể tự tin rằng nó có mọi thứ cho đến khi @ 5.
Vì vậy, vấn đề thực tế chưng cất: làm thế nào có thể điều này được xác định một cách an toàn mà không cần buộc SERIALIZABLE
hoặc nếu không làm tổn thương nghiêm trọng hiệu suất?
Như bạn có thể nói tôi đã mượn ý tưởng này từ SQL Server, nơi mà sự cố này được giải quyết một cách trivially bởi hàm min_active_rowversion()
. Hàm này sẽ trả về @ 6 trong trường hợp trên, vì vậy, new_anchor
của bạn có thể an toàn là min_active_rowversion() - 1
. Tôi đã có một ý tưởng làm thế nào điều này có thể được thực hiện trong Postgres bằng cách sử dụng một bảng active_rowversions
, gây nên, và SELECT min(id) FROM active_rowversions
, nhưng điều đó sẽ yêu cầu cách ly READ UNCOMMITTED
, không có sẵn trong Postgres.
Tôi thực sự đánh giá cao bất kỳ trợ giúp hoặc ý tưởng nào.