Tôi có một thủ tục được lưu trữ truy vấn một bảng xếp hàng bận rộn được sử dụng để phân phối công việc trong hệ thống của chúng tôi. Bảng trong câu hỏi có khóa chính trên WorkID và không trùng lặp.
Một phiên bản đơn giản của truy vấn là:
INSERT INTO #TempWorkIDs (WorkID)
SELECT
W.WorkID
FROM
dbo.WorkTable W
WHERE
(@bool_param = 0 AND
((W.InProgress = 0
AND ISNULL(W.UserID, -1) != @userid_param
AND (@bool_filtered = 0
OR W.TypeID IN (SELECT TypeID FROM #Types AS t)))
OR
(@bool_param = 1
AND W.InProgress = 1
AND W.UserID != @userid_param)
OR
(@Auto_Param = 0
AND W.UserID = @userid_param)))
OR
(@bool_param = 1 AND W.UserID = @userid_param)
OPTION
(RECOMPILE)
Các #Typesbảng được phổ biến trước đó trong thủ tục.
Như tôi đã nói, WorkTableđang bận và đôi khi trong khi truy vấn này đang chạy, tôi TẠM một trong các bản ghi đang di chuyển từ một bộ các bộ lọc sang bộ lọc WHEREkhác. Cụ thể, điều này xảy ra khi ai đó bắt đầu làm việc trên một mục và W.InProgressthay đổi từ 0 thành 1. Khi điều này xảy ra, tôi bị vi phạm khóa trùng lặp khi tôi cố thêm khóa chính vào bảng tạm thời mà truy vấn này đang chèn vào.
Tôi đã xác nhận trong kế hoạch truy vấn được tạo khi xảy ra lỗi không có sự song song, mức cô lập READ COMMITTEDvà không có bản ghi trùng lặp trong bảng nguồn. Bạn cũng có thể thấy không có JOINcách nào khác để có được các sản phẩm cartesian ở đây.
Đây là kế hoạch truy vấn ẩn danh:
Câu hỏi là, điều gì gây ra sự trùng lặp và làm thế nào tôi có thể dừng nó lại?
Tôi nghĩ READ COMMITTEDnên làm việc ở đây, tôi cần khóa. Tôi gần như tích cực các bản sao xảy ra khi InProgressbit trên bản ghi thay đổi trong khi tôi truy vấn. Tôi biết điều này bởi vì bảng lưu trữ thời gian của sự thay đổi đó và nó chỉ trong một phần nghìn giây khi tôi truy vấn và gặp lỗi.

