2015-02-11 12 views
5

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]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:

  1. Ask cơ sở dữ liệu cho một thích hợp new_anchor.
  2. Thực hiện SELECT * FROM emps WHERE rowversion>3 and rowversion<=new_anchor.
  3. 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.

Trả lời

5

Hóa ra giải pháp đơn giản hơn nhiều so với suy nghĩ ban đầu, nhờ vào số System Information Functions của Postgres.

  • txid_current() có thể được sử dụng để kích hoạt bản ghi rowversion.
  • txid_snapshot_min(txid_current_snapshot()) có thể được sử dụng để nhận giao dịch hoạt động tối thiểu giống như cách người dùng SQL Server có thể sử dụng min_active_rowversion().

Phần tốt nhất là đây là 64-bit, vĩnh viễn, không chịu hút bụi:

Những chức năng xuất khẩu một định dạng 64-bit được mở rộng với một "kỷ nguyên" truy cập để nó sẽ không quấn quanh trong suốt quá trình cài đặt.

Postgres thực sự tuyệt vời.

Các vấn đề liên quan