Saya memiliki prosedur tersimpan yang menanyakan tabel antrian sibuk yang digunakan untuk mendistribusikan pekerjaan di sistem kami. Tabel tersebut memiliki kunci utama pada WorkID dan tidak ada duplikat.
Versi kueri yang disederhanakan adalah:
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)
The #Types
meja dihuni awal prosedur.
Seperti yang saya katakan, WorkTable
sibuk, dan kadang-kadang saat kueri ini berjalan, saya MENCURANGI salah satu catatan bergerak dari satu set filter WHERE
ke yang lain. Khususnya, ini terjadi ketika seseorang mulai mengerjakan suatu item, dan W.InProgress
perubahan dari 0 menjadi 1. Ketika ini terjadi, saya mendapatkan pelanggaran kunci duplikat ketika saya mencoba menambahkan kunci utama ke tabel temp sementara kueri ini dimasukkan ke dalam.
Saya telah mengkonfirmasi dalam rencana kueri yang dihasilkan ketika kesalahan terjadi bahwa tidak ada paralelisme, tingkat isolasi READ COMMITTED
, dan tidak ada rekaman duplikat di tabel sumber. Anda juga dapat melihat tidak ada JOIN
cara lain untuk mendapatkan produk kartesian di sini.
Ini adalah paket permintaan anonim:
Pertanyaannya adalah, apa yang menyebabkan duplikat dan bagaimana saya bisa menghentikannya?
Saya pikir READ COMMITTED
harus bekerja di sini, saya perlu mengunci. Saya hampir positif dupes terjadi ketika InProgress
bit pada catatan berubah saat saya bertanya. Saya tahu ini karena tabel menyimpan waktu perubahan itu dan itu dalam milidetik ketika saya meminta dan mendapatkan kesalahan.