问题描述
|
我有一个执行以下操作(简化)的存储过程:
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中创建一个锁。如果在第一个过程仍在执行时调用第二个过程,则应等待第二个过程完成,对吗?
目前这造成了僵局,有什么想法吗?
解决方法
insert
查询所需要的锁与select
不同。 select
的锁定会阻止第二个insert
,但不会阻止第二个select
。因此,两个查询都可以以ѭ2开始,但是它们都阻塞在另一个s1上。
您可以通过要求第一个查询锁定整个表来解决此问题:
SET @intNo = (SELECT MAX(intNo) + 1 FROM tbl with (tablockx))
^^^^^^^^^^^^^^^
这会使第二笔交易的ѭ2等待第一笔交易的完成。
,使它更简单,使您只有一条语句而无需事务
--BEGIN TRANSACTION not needed
INSERT INTO tbl(intNo)
OUTPUT INSERTED.intNo
SELECT MAX(intNo) + 1 FROM tbl WITH (TABLOCK)
--COMMIT TRANSACTION not needed
虽然,为什么不使用IDENTITY ...?