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

Lời khuyên khóa hoặc NOWAIT để tránh phải chờ các hàng bị khóa?

FOR UPDATE NOWAIT chỉ là ý kiến ​​hay nếu bạn nhấn mạnh vào việc khóa một hàng cụ thể, điều này không những gì bạn cần. Bạn chỉ muốn bất kỳ hàng đủ điều kiện, có sẵn (đã mở khóa). Sự khác biệt quan trọng là đây (trích dẫn hướng dẫn sử dụng cho Postgres 9.4):

Với NOWAIT , câu lệnh báo cáo một lỗi, thay vì chờ đợi, nếu một hàng đã chọn không thể được khóa ngay lập tức.

Các truy vấn giống hệt nhau rất có thể sẽ cố gắng khóa cùng một lượt chọn tùy ý. FOR UPDATE NOWAIT sẽ chỉ cứu trợ với một ngoại lệ (sẽ khôi phục toàn bộ giao dịch trừ khi bạn mắc lỗi) và bạn phải thử lại.

Giải pháp trong câu trả lời được tham chiếu của tôi trên dba.SE sử dụng kết hợp FOR UPDATE thuần túy kết hợp với pg_try_advisory_lock() :

pg_try_advisory_lock tương tự như pg_advisory_lock , ngoại trừ chức năng sẽ không đợi khóa khả dụng. Nó sẽ không lấy được khóa ngay lập tức và trả về true hoặc trả về false nếu không thể lấy được khóa ngay lập tức.

Vì vậy, lựa chọn tốt nhất của bạn là ... giải pháp thay thế thứ ba: FOR UPDATE SKIP LOCKED mới trong Postgres 9.5, thực hiện cùng một hành vi mà không cần gọi hàm bổ sung.

Hướng dẫn sử dụng cho Postgres 9.5 so sánh hai tùy chọn, giải thích thêm về sự khác biệt:

Để ngăn hoạt động chờ các giao dịch khác gửi đến, hãy sử dụng NOWAIT hoặc SKIP LOCKED lựa chọn. Với NOWAIT , câu lệnh báo cáo lỗi, thay vì đợi, nếu một hàng đã chọn không thể khóa ngay lập tức. Với SKIP LOCKED , mọi hàng đã chọn không thể khóa ngay lập tức sẽ bị bỏ qua.

Trên Postgres 9.4 trở lên tùy chọn tốt nhất tiếp theo của bạn là sử dụng pg_try_advisory_xact_lock(id) kết hợp với FOR UPDATE như được chứng minh trong câu trả lời được tham chiếu:

  • CẬP NHẬT Postgres… LIMIT 1

(Cũng với cách triển khai với FOR UPDATE SKIP LOCKED .)

Qua một bên

Nói một cách chính xác, bạn nhận được những lựa chọn tùy ý, không thực sự ngẫu nhiên. Đó có thể là một điểm khác biệt quan trọng.
Phiên bản đã được kiểm toán của truy vấn của bạn nằm trong câu trả lời của tôi cho câu hỏi khác của bạn.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thêm chỉ báo thứ tự cho một ngày trong PostgreSQL

  2. Django cố định không thành công, cho biết DatabaseError:giá trị quá dài đối với ký tự loại thay đổi (50)

  3. pgDash Alternatives - Giám sát cơ sở dữ liệu PostgreSQL với ClusterControl

  4. Hibernate, Postgres &Loại mảng

  5. Django-DB-Migrations:không thể ALTER TABLE vì nó có các sự kiện kích hoạt đang chờ xử lý