Có cách nào để ngăn chặn sự bế tắc trong khi duy trì các truy vấn tương tự không?
Biểu đồ khóa chết cho thấy bế tắc cụ thể này là một bế tắc chuyển đổi được liên kết với tra cứu dấu trang (tra cứu RID trong trường hợp này):
Như câu hỏi lưu ý, rủi ro bế tắc chung phát sinh do các truy vấn có thể có được các khóa không tương thích trên cùng một tài nguyên theo các thứ tự khác nhau. Các SELECT
truy vấn cần phải truy cập vào các chỉ số trước khi bàn do sự tra cứu RID, trong khi UPDATE
Sửa truy vấn bảng đầu tiên, sau đó chỉ số.
Loại bỏ bế tắc đòi hỏi phải loại bỏ một trong các thành phần bế tắc. Sau đây là các tùy chọn chính:
- Tránh tra cứu RID bằng cách bao phủ chỉ mục không bao gồm. Điều này có thể không thực tế trong trường hợp của bạn vì
SELECT
truy vấn trả về 26 cột.
- Tránh tra cứu RID bằng cách tạo một chỉ mục cụm. Điều này sẽ liên quan đến việc tạo một chỉ mục cụm trên cột
Proposal
. Điều này đáng để xem xét, mặc dù có vẻ như cột này thuộc loại uniqueidentifier
, có thể hoặc không phải là một lựa chọn tốt cho một chỉ mục được nhóm, tùy thuộc vào các vấn đề rộng hơn.
- Tránh lấy các khóa được chia sẻ khi đọc bằng cách bật tùy chọn
READ_COMMITTED_SNAPSHOT
hoặc SNAPSHOT
cơ sở dữ liệu. Điều này sẽ yêu cầu kiểm tra cẩn thận, đặc biệt là đối với mọi hành vi chặn được thiết kế sẵn. Mã kích hoạt cũng sẽ yêu cầu thử nghiệm để đảm bảo logic thực hiện chính xác.
- Tránh lấy các khóa được chia sẻ khi đọc bằng cách sử dụng
READ UNCOMMITTED
mức cô lập cho SELECT
truy vấn. Tất cả các hãy cẩn thận thông thường áp dụng.
- Tránh thực hiện đồng thời hai truy vấn được đề cập bằng cách sử dụng khóa ứng dụng độc quyền (xem sp_getapplock ).
- Sử dụng gợi ý khóa bảng để tránh đồng thời. Đây là một cái búa lớn hơn tùy chọn 5, vì nó có thể ảnh hưởng đến các truy vấn khác, không chỉ hai truy vấn được xác định trong câu hỏi.
Tôi bằng cách nào đó có thể lấy X-Lock trên chỉ mục trong giao dịch cập nhật trước khi cập nhật để đảm bảo truy cập bảng và chỉ mục theo cùng một thứ tự
Bạn có thể thử điều này, bằng cách gói cập nhật trong một giao dịch rõ ràng và thực hiện SELECT
với một XLOCK
gợi ý về giá trị chỉ mục không bao gồm trước khi cập nhật. Điều này phụ thuộc vào bạn biết chắc chắn giá trị hiện tại trong chỉ mục không bao gồm là gì, làm cho kế hoạch thực hiện đúng và dự đoán chính xác tất cả các tác dụng phụ của việc sử dụng khóa bổ sung này. Nó cũng dựa vào công cụ khóa không đủ thông minh để tránh mất khóa nếu nó được đánh giá là dư thừa .
Tóm lại, trong khi nguyên tắc này là khả thi, tôi không khuyên bạn nên dùng nó. Thật quá dễ dàng để bỏ lỡ một cái gì đó, hoặc vượt qua chính mình theo những cách sáng tạo. Nếu bạn thực sự phải tránh những bế tắc này (thay vì chỉ phát hiện ra chúng và thử lại), tôi sẽ khuyến khích bạn xem xét các giải pháp tổng quát hơn được liệt kê ở trên.