I have a table with a PK and a unique non-clustered index, as follows:
CREATE TABLE Table1
(
Id INT IDENTITY(1,1) NOT NULL,
Field1 VARCHAR(25) NOT NULL,
Field2 VARCHAR(25) NULL,
CONSTRAINT PK_Table1 PRIMARY KEY CLUSTERED (Id ASC)
)
CREATE UNIQUE NONCLUSTERED INDEX IX_Field1_Field2 ON Table1
(
Field1 ASC,
Field2 ASC
)
WITH
(
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
I have 2 jobs whose execution times I find are overlapping each other. They both include the same INSERT into this table and frequently the job that starts last fails because it tries to insert a record into Table1 with a duplicate index key value.
INSERT Table1
SELECT Field1, Field2
FROM SomeOtherTable sot WITH (NOLOCK)
WHERE NOT EXISTS (
SELECT 1
FROM Table1 t1
WHERE sot.Field1 = t1.Field1
AND sot.Field2 = t1.Field2
)
From what I've been able to discern, the INSERT in Job1 is still executing when the NOT EXISTS from Job2 is evaluated resulting in Job2 trying to insert a duplicate key value. It seems to me that the locking for Table1 is not happening as expected.
I'm at a loss as to why this is happening. Would this have anything to do with the NOLOCK hint used in the INSERT? I didn't think that that hint would include Table1 in its scope, only SomeOtherTable.
I know I can mitigate the duplicate key error by setting IGNORE_DUP_KEY to ON for the index, and that would be fine for us in this situation. I would like to know, though, why the duplicate is showing up in the 2nd INSERT.
WITH (NOLOCK)is allowing both queries to read the same items, and attempt to insert them. – Max Vernon Mar 19 at 19:56