Reputation: 5866
I would like to lock some rows in a table with a SELECT statement in SP. I have transaction in my SP. I would like to lock all rows that I SELECT after BEGIN TRANSACTION.So, I would like to release those rows after COMMIT/ROLLBACK.
I have tried XLOCK,UPDLOCK,HOLDLOCK but none of them does what I expect.
Here is my sample code...
BEGIN TRANSACTION
-- I WANT TO LOCK EMPLOYEES LIVE IN ISTANBULL
SELECT ID FROM EMPLOYEES WITH(XLOCK) WHERE CITY='ISTANBUL'
....
....
....
COMMIT
-- LOCKED ROWS SHOULD BE RELEASED AFTER COMMIT.
any suggestion?
Upvotes: 1
Views: 9803
Reputation: 46
Add the holdlock hint to the xlock hint.
Eg.
begin tran
select ... from ... with (xlock, holdlock) where ...
commit tran
Upvotes: -1
Reputation: 1912
Your code should work fine.
Suppose, you are selecting rows with UPDLOCK/XLOCK.
First Transaction
BEGIN TRAN
SELECT ID FROM EMPLOYEES WITH(UPDLOCK, XLOCK) WHERE CITY='ISTANBUL'
--COMMIT TRAN (Stopping commit to keep the lock running)
Now try run following in another window.
Second Transaction
BEGIN TRAN
SELECT ID FROM EMPLOYEES WITH(UPDLOCK, XLOCK) WHERE CITY='ISTANBUL'
COMMIT TRAN
Your second transaction will not be able to select until you commit your first transaction. Because multiple UPDLOCK or XLOCK can't be applied together on a resource.
Now, if you read rows without locking with uncommitted first transaction then second transaction will not be prevented by the first.
Second Transaction
BEGIN TRAN
SELECT ID FROM EMPLOYEES WHERE CITY='ISTANBUL'
COMMIT TRAN
Because in second transaction no lock applied so it will not be prevented by first transactions UPDLOCK or XLOCK.
Now to prevent any read with another read you need to change your ISOLATION LEVEL TO SERIALIZABLE.
First Transaction
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SELECT ID FROM EMPLOYEES WHERE CITY='ISTANBUL'
--COMMIT TRAN (Stopping commit to keep the lock running)
Second Transaction
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SELECT ID FROM EMPLOYEES WHERE CITY='ISTANBUL'
COMMIT TRAN
Now second transaction will be blocked by first transaction. Though no lock applied during read but in transaction isolation level SERIALIZABLE a read transaction will block read of another transaction over same resource.
Now If you select with NOLOCK then there is no transaction lock or isolation level exists to block you.
Hope these helps :)
Upvotes: 9