/**
--index level locking
This example below shows that locking hints dont necessarily work the way you think.
Summary of whats going on:
Proc 1 accesses the data required via index 1 taking out an updlock
Proc 2 Accesses the same data via index 2 taking out an updlock
Proc 1 then tries to update all the rows in the data (including the field involved in index 2)
Proc 2 then tries to update all the rows in the data (including the field involved in index 1) --deadlock occurs.
Basically when you take an update lock out on the row the clustered index row isnt necessarily locked
**/
CREATE TABLE tab_hmk_IndexLockingExample
(
PrimaryID Int ,
FirstName Varchar(20),
LastName Varchar(20)
)
CREATE UNIQUE CLUSTERED INDEX idx_PrimaryID ON tab_hmk_IndexLockingExample(PrimaryID)
GO
CREATE NONCLUSTERED INDEX idx_NonClustered_FirstName ON tab_hmk_IndexLockingExample(FirstName)
GO
CREATE NONCLUSTERED INDEX idx_NonClustered_LastName ON tab_hmk_IndexLockingExample(LastName)
GO
Insert into tab_hmk_IndexLockingExample(PrimaryID, FirstName, LastName) Values(1, 'Joe', 'Bloggs')
Insert into tab_hmk_IndexLockingExample(PrimaryID, FirstName, LastName) Values(2, 'Mike', 'Smith')
Insert into tab_hmk_IndexLockingExample(PrimaryID, FirstName, LastName) Values(3, 'Wayne', 'Rooney')
CREATE PROC hmk_GetDataOnFirstIndex
AS
BEGIN
--start the transaction
BEGIN TRANSACTION
--select the data doing an updlock on the row - should prevent further updates to the row NOTE - accesses data on the first Index
SELECT FirstName
FROM tab_hmk_IndexLockingExample WITH (UPDLOCK)
WHERE FirstName = 'Joe'
WAITFOR DELAY '00:00:30'
--Try Updating the data, including the lastname (involved in the second index)
Update tab_hmk_IndexLockingExample
SET FirstName = FirstName, LastName= LastName
Where FirstName = 'Joe'
--Commit Transaction
--rollback Transaction
END
--run this proc from a seperate window
CREATE PROC hmk_GetDataOnSecondIndex
AS
BEGIN
--start the transaction
BEGIN TRANSACTION
--select the data doing an updlock on the row - should prevent further updates to the row, NOTE on using different INDEX
SELECT LastName
FROM tab_hmk_IndexLockingExample WITH (UPDLOCK)
WHERE LastName = 'Bloggs'
WAITFOR DELAY '00:00:30'
--Now try and update the row including the data involved in the first index
--Update the data
Update tab_hmk_IndexLockingExample
SET FirstName = FirstName, LastName = LastName
Where Lastname = 'Bloggs'
commit tran
END