This work follows on from Snapshot isolation transaction aborted due to update conflict in SQL Server due to FK checks.
After looking at this excellent article (https://sqlperformance.com/2021/06/sql-performance/foreign-keys-blocking-update-conflicts#comment-167645)
I run this code to create the database:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Parent]
(
[ParentID] [int] NOT NULL,
[UpdateTime] [datetime] NOT NULL,
CONSTRAINT [PK dbo.Parent ParentID]
PRIMARY KEY CLUSTERED ([ParentID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Child]
(
[ChildID] [int] NOT NULL,
[ParentID] [int] NULL,
[UpdateTime] [datetime] NULL,
CONSTRAINT [PK dbo.Child ChildID]
PRIMARY KEY CLUSTERED ([ChildID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Child] WITH CHECK
ADD CONSTRAINT [FK dbo.Child to dbo.Parent]
FOREIGN KEY([ParentID]) REFERENCES [dbo].[Parent] ([ParentID])
GO
ALTER TABLE [dbo].[Child] CHECK CONSTRAINT [FK dbo.Child to dbo.Parent]
GO
CREATE TABLE [dbo].[Dummy]
(
[x] [int] NULL
) ON [PRIMARY]
GO
The database must allow snapshot isolation and have read committed snapshot enabled.
Populated the database as follows:
DELETE FROM dbo.Child
DELETE FROM dbo.Parent
GO
-- Insert parent rows
INSERT INTO dbo.Parent (ParentID, UpdateTime) VALUES (1, GETUTCDATE());
INSERT INTO dbo.Parent (ParentID, UpdateTime) VALUES (2, GETUTCDATE());
INSERT INTO dbo.Parent (ParentID, UpdateTime) VALUES (3, GETUTCDATE());
-- Insertion a child row
INSERT INTO dbo.Child select 101, 2, GetUTCDate()
go
Then run these 2 scripts (as directed):
-- Session 1 - part one (1st bit to run)
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRANSACTION;
-- Ensure snapshot transaction is started
SELECT COUNT_BIG(*) FROM dbo.Dummy AS D;
-- Session 1 - part two (3rd bit to run)
DELETE FROM dbo.Parent WHERE ParentID = 3
-- Session 2 - part one (2nd bit to run)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRANSACTION;
UPDATE dbo.Child
SET UpdateTime = GETUTCDATE()
WHERE ParentID = 1
INSERT INTO dbo.Child
SELECT 201, 2, GetUTCDate()
-- Session 2 - part two (4th bit to run)
COMMIT TRANSACTION;
and Session 1 generates the update error as expected:
Msg 3960, Level 16, State 1, Line 10
Snapshot isolation transaction aborted due to update conflict. You cannot use snapshot isolation to access table 'dbo.Child' directly or indirectly in database 'Example Changed' to update, delete, or insert the row that has been modified or deleted by another transaction. Retry the transaction or change the isolation level for the update/delete statement.
According to the article this should be eliminated by changing the PK to non-clustered and adding a unique clustered index but the same error is generated. Doing this should get round the FK issue but does not seem to even though the execution plan implies that it should.
Why is this now the case?
Thanks Ian