Về cơ bản, bạn đang mô tả quy trình làm việc dựa trên hàng đợi cổ điển và bạn nên cân nhắc sử dụng thực tế hàng đợi .
Để tiện cho việc thảo luận, đây là cách bạn đạt được điều mình mong muốn:
- xác nhận tài nguyên cụ thể:
SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK) WHERE key = @key
. Sẽ chặn nếu tài nguyên đã được xác nhận quyền sở hữu. Sử dụng thời gian chờ khóa để trả về ngoại lệ nếu tài nguyên đã được xác nhận quyền sở hữu. khóakey
phải được lập chỉ mục và duy nhất. - tài nguyên có sẵn tiếp theo:
SELECT ... FROM resources WITH (UPDLOCK, ROWLOCK, READPAST) ORDER BY <accessorder>
. Bạn phải xác định thứ tự bằng cách thể hiện ưu tiên của tài nguyên (cũ nhất, ưu tiên cao nhất, v.v.) - giải phóng một tài nguyên đã được xác nhận quyền sở hữu:
COMMIT
giao dịch của bạn.
Ý chính của vấn đề là sử dụng các gợi ý khóa phù hợp và loại vấn đề này yêu cầu các gợi ý khóa rõ ràng để giải quyết. UPDLOCK sẽ hoạt động như một khóa 'xác nhận quyền sở hữu'. ROWLOCK tạo ra độ chi tiết phù hợp ngăn máy chủ 'tối ưu hóa' để khóa trang. READPAST cho phép bạn bỏ qua các tài nguyên đã xác nhận quyền sở hữu. Đặt UPDLOCK trên các hàng sẽ khóa hàng và cho phép bạn cập nhật nó sau đó, nhưng sẽ ngăn các hoạt động khác như các lệnh CHỌN được cam kết đọc thông thường sẽ chặn trên hàng bị khóa. Mặc dù vậy, ý tưởng là bạn sẽ CẬP NHẬT hàng, điều này sẽ đặt một khóa X không thể tránh khỏi. Nếu bạn muốn giữ cho bảng có sẵn hơn, bạn có thể sử dụng khóa ứng dụng thay vào đó, nhưng khó hơn đáng kể để thực hiện một cách chính xác. Bạn sẽ cần yêu cầu khóa ứng dụng trên bộ mô tả chuỗi trên tài nguyên, như giá trị khóa hoặc CHECKSUM
của khóa hoặc đó là %%LOCKRES%%
giá trị. Khóa ứng dụng cho phép bạn tách phạm vi 'xác nhận quyền sở hữu' khỏi giao dịch bằng cách yêu cầu khóa ứng dụng ở phạm vi 'phiên', nhưng sau đó bạn phải hủy bỏ xác nhận quyền sở hữu theo cách thủ công (khóa ứng dụng trong phạm vi 'giao dịch' được phát hành tại thời điểm cam kết) . Tuy nhiên, hãy lưu ý, có hàng nghìn cách để tự bắn vào chân mình bằng khóa ứng dụng.