PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách đánh dấu nr hàng nhất định trong bảng khi truy cập đồng thời

Trong câu trả lời liên quan mà bạn đang đề cập đến:

  • CẬP NHẬT Postgres ... LIMIT 1

Mục tiêu là khóa một hàng tại một thời điểm. Điều này hoạt động tốt khi có hoặc không có khóa tư vấn, bởi vì không có cơ hội cho khóa - miễn là bạn không cố gắng khóa nhiều hàng hơn trong cùng một giao dịch.

Ví dụ của bạn khác ở chỗ bạn muốn khóa 3000 hàng cùng một lúc . Có khả năng xảy ra bế tắc, ngoại trừ trường hợp tất cả các thao tác ghi đồng thời khóa các hàng theo cùng một thứ tự nhất quán. Theo tài liệu:

Cách bảo vệ tốt nhất chống lại các deadlock nói chung là tránh chúng bằng cách chắc chắn rằng tất cả các ứng dụng sử dụng cơ sở dữ liệu đều có khóa trên nhiều đối tượng theo một thứ tự nhất quán.

Triển khai điều đó bằng ORDER BY trong truy vấn con của bạn.

UPDATE cargo_item item
SET job_id = 'SOME_UUID', job_ts = now()
FROM  ( 
   SELECT id
   FROM   cargo_item
   WHERE  state='NEW' AND job_id is null 
   ORDER  BY id
   LIMIT  3000
   FOR UPDATE
   ) sub
WHERE  item.id = sub.id;

Điều này là an toàn và đáng tin cậy, miễn là tất cả các giao dịch có được các khóa theo cùng một thứ tự và các cập nhật đồng thời của các cột thứ tự không được mong đợi. (Đọc hộp "THẬN TRỌNG" màu vàng ở cuối chương này trong sách hướng dẫn.) Vì vậy, điều này sẽ an toàn trong trường hợp của bạn, vì bạn sẽ không cập nhật id cột.

Hiệu quả, chỉ một ứng dụng khách tại một thời điểm có thể thao tác các hàng theo cách này. Các giao dịch đồng thời sẽ cố gắng khóa các hàng giống nhau (bị khóa) và đợi giao dịch đầu tiên kết thúc.

Khóa tư vấn rất hữu ích nếu bạn có nhiều hoặc rất dài các giao dịch đồng thời (có vẻ như bạn không làm vậy). Chỉ với một số ít, nhìn chung sẽ rẻ hơn nếu chỉ sử dụng truy vấn trên và để các giao dịch đồng thời chờ đến lượt.

Tất cả trong một CẬP NHẬT

Có vẻ như quyền truy cập đồng thời không phải là vấn đề đối với thiết lập của bạn. Đồng thời là một vấn đề do giải pháp hiện tại của bạn tạo ra.

Thay vào đó, hãy thực hiện tất cả trong một UPDATE duy nhất . Chỉ định các lô n số (trong ví dụ là 3000) cho từng UUID và cập nhật tất cả cùng một lúc. Sẽ nhanh nhất.

UPDATE cargo_item c
SET    job_id = u.uuid_col
     , job_ts = now()
FROM  (
   SELECT row_number() OVER () AS rn, uuid_col
   FROM   uuid_tbl WHERE  <some_criteria>  -- or see below
   ) u
JOIN (
   SELECT (row_number() OVER () / 3000) + 1 AS rn, item.id 
   FROM   cargo_item
   WHERE  state = 'NEW' AND job_id IS NULL
   FOR    UPDATE   -- just to be sure
   ) c2 USING (rn)
WHERE  c2.item_id = c.item_id;

Những điểm chính

  • Cắt bớt phép chia số nguyên. Bạn nhận được 1 cho 3000 hàng đầu tiên, 2 cho 3000 hàng tiếp theo. vv

  • Tôi chọn hàng tùy ý, bạn có thể áp dụng ORDER BY trong cửa sổ cho row_number() để gán các hàng nhất định.

  • Nếu bạn không có bảng UUID để gửi đi (uuid_tbl ), sử dụng VALUES biểu hiện để cung cấp cho họ. Ví dụ.

  • Bạn nhận được hàng loạt 3000 hàng. Lô cuối cùng sẽ thiếu 3000 nếu bạn không tìm thấy bội số 3000 để chỉ định.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hàm SQL rất chậm so với truy vấn không có trình bao bọc hàm

  2. Lời gọi hàm PostgreSQL

  3. Xây dựng cơ sở dữ liệu khả dụng cao cho Moodle bằng PostgreSQL

  4. Hiểu các loại ngày và chức năng của PostgreSQL (bằng các ví dụ)

  5. Chèn trình kích hoạt để Cập nhật bảng khác bằng PostgreSQL