I have a table with a FK and I want to update a row in that table without being blocked by another transaction which is updating the parent row at the same time. Here is an example:
CREATE TABLE dbo.ParentTable ( PARENT_ID int NOT NULL, VALUE varchar(128) NULL, CONSTRAINT PK_ParentTable PRIMARY KEY (PARENT_ID) ) GO CREATE TABLE dbo.ChildTable ( CHILD_ID int NOT NULL, PARENT_ID INT NULL, VALUE varchar(128) NULL, CONSTRAINT PK_ChildTable PRIMARY KEY (CHILD_ID), CONSTRAINT FK_ChildTable__ParentTable FOREIGN KEY (PARENT_ID) REFERENCES dbo.ParentTable (PARENT_ID) ) GO INSERT INTO ParentTable(PARENT_ID, VALUE) VALUES (1, 'Some value'); INSERT INTO ChildTable(CHILD_ID, PARENT_ID, VALUE) VALUES (1, 1, 'Some value'); GO
Now I have 2 transactions running at the same time:
The first transaction:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRAN UPDATE ParentTable SET VALUE = 'Test' WHERE PARENT_ID = 1;
The second transaction:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRAN UPDATE ChildTable SET VALUE = 'Test', PARENT_ID = 1 WHERE CHILD_ID = 1;
If 'UPDATE ParentTable' statement runs a bit earlier, then 'UPDATE ChildTable' statement is blocked untill the first transaction is committed or rollbacked. It happens because SQL Server acquires shared locks when validating foreign keys, even if the transaction is using read uncommitted, read committed snapshot (read committed using row versioning) or snapshot isolation level. I cannot see why change in the ParentTable.VALUE should prevent me from updating ChildTable. Please note that ParentTable.PARENT_ID is not changed by the first transaction, which means that from FK's point of view whatevere is set to the ParentTable.VALUE is never a problem for referential integrity. So, such blocking behavior seems to me not logical. Furthermore, it contradicts to the MSDN:
Transactions running at the READ UNCOMMITTED level do not issue shared locks to prevent other transactions from modifying data read by the current transaction. READ UNCOMMITTED transactions are also not blocked by exclusive locks that would prevent the current transaction from reading rows that have been modified but not committed by other transactions.
Does anybody know how to workaround the issue? In other words, are there any tricks to avoid shared locks when validating foreign keys? (Disabling FK is not an option.) Thank you.
Alexey