I’m writing a SQL Server stored procedure in which I want to lock a table for update before executing the body of the stored procedure. I don’t want to prevent other processes from reading the table, but I do want to prevent other processes updating the table.
Here is my first attempt:
CREATE PROCEDURE someProcedure
BEGIN
SET TRANSACTION ISOLATION LEVEL READ COMITTED
BEGIN TRANSANCTION
SELECT COUNT(*) FROM TheTable WITH (UPDLOCK, TABLOCK)
-- Pause procedure so that we can view the locks with sp_lock
WAITFOR DELAY '00:15'
-- Do stuff
COMMIT
END
When I execute the stored procedure, and invoke sp_lock, I see that the table is indeed locked. However, it’s locked with an Exclusive lock instead of an update lock:
spid | dbid | ObjId | IndId | Type | Resource | Mode | Status
------------------------------------------------------------------
63 | 10 | 233208031 | 0 | TAB | | X | GRANT
How can I get an update (U) lock instead?
You said:
You simply need a shared read lock for the duration of the TXN. This means no other process can get a “write” lock, in conjunction with a TABLOCK. And you don’t need COUNT either.
Why do you think you want an UPDATE LOCK?
HOLDLOCK or SERIALIZABLE
Edit, after comment:
You can’t specify “exclusive lock” and allow other processes to read. The concepts are mutually exclusive. You want to prevent writes to the entire table, which a persisted shared/read lock will do. This is where SERIALIZABLE comes in.
From “Lock Modes”
So: a shared lock disallows writes and can be made to persist by making it SERIALIZABLE