I've got a stored procedure that does the following (Simplified):
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRANSACTION
DECLARE @intNo int
SET @intNo = (SELECT MAX(intNo) + 1 FROM tbl)
INSERT INTO tbl(intNo)
Values (@intNo)
SELECT intNo
FROM tbl
WHERE (intBatchNumber = @intNo - 1)
COMMIT TRANSACTION
My issue is that when two or more users execute this at the same time I am getting deadl开发者_JAVA百科ocks. Now as I understand it the moment I do my first select in the proc this should create a lock in tbl. If the second procedure is then called while the first procedure is still executing it should wait for it to complete right?
At the moment this is causing a deadlock, any ideas?
The insert
query requires a different lock than the select
. The lock for select
blocks a second insert
, but it does not block a second select
. So both queries can start with the select
, but they both block on the other's insert
.
You can solve this by asking the first query to lock the entire table:
SET @intNo = (SELECT MAX(intNo) + 1 FROM tbl with (tablockx))
^^^^^^^^^^^^^^^
This will make the second transaction's select
wait for the complete first transaction to finish.
Make it simpler so you have one statement and no transaction
--BEGIN TRANSACTION not needed
INSERT INTO tbl(intNo)
OUTPUT INSERTED.intNo
SELECT MAX(intNo) + 1 FROM tbl WITH (TABLOCK)
--COMMIT TRANSACTION not needed
Although, why aren't you using IDENTITY...?
精彩评论