我有一个存储过程执行以下操作(简化):
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
我的问题是,当两个或多个用户同时执行此操作时,我会遇到死锁。现在据我所知,当我在proc中进行第一次选择时,应该在tbl中创建一个锁定。如果在第一个程序仍在执行时调用第二个程序,它应该等待它完成吗?
目前导致僵局,任何想法?
答案 0 :(得分:3)
insert
查询需要与select
不同的锁定。 select
的锁定阻止了第二个insert
,但它不会阻止第二个select
。因此,这两个查询都可以从select
开始,但它们都会阻止另一个insert
。
您可以通过询问第一个查询来锁定整个表来解决此问题:
SET @intNo = (SELECT MAX(intNo) + 1 FROM tbl with (tablockx))
^^^^^^^^^^^^^^^
这将使第二个交易的select
等待完成第一笔交易。
答案 1 :(得分:1)
使它更简单,因此你有一个陈述而没有交易
--BEGIN TRANSACTION not needed
INSERT INTO tbl(intNo)
OUTPUT INSERTED.intNo
SELECT MAX(intNo) + 1 FROM tbl WITH (TABLOCK)
--COMMIT TRANSACTION not needed
虽然,你为什么不使用IDENTITY ......?