我分别在两个会话中有两个测试事务。假设这两个事务将同时运行。我尝试做的是让一个事务在另一个事务完成后正确插入发票号。没有重复。我做了如下。但是如果我在会话2中使用(tablockx)删除它们将不再工作。我查了线书,但没有回答。有人会帮忙吗? Serializable将无法工作,因为这两个SELECT希望彼此独占。感谢。
在第1节:
begin transaction
declare @i int
select @i=MAX(InvNumber) from Invoice
with(tablockx)
where LocName='A'
waitfor delay '00:00:10'
set @i=@i+1
insert into Invoice values('A',@i);
commit
在第2节:
begin transaction
declare @i int
select @i=MAX(InvNumber) from Invoice
with(tablockx)
where LocName='A'
set @i=@i+1
insert into Invoice values('A',@i);
commit
答案 0 :(得分:1)
这将有效,但也会完全阻止对该表的所有其他访问。
如果执行WITH(UPDLOCK, HOLDLOCK)
,您可能会以较低的粒度(比表格)和模式(而不是独占)锁定。
HOLDLOCK
给出了可序列化的语义,因此只需锁定索引顶部的范围(如果LocName,InvNumber
上有一个)。
UPDLOCK
确保两个并发事务不能同时拥有相同的锁,但与exclusive不同,不会阻止未使用提示的其他(普通)读者。
BEGIN TRANSACTION
DECLARE @i INT
SELECT @i = MAX(InvNumber)
FROM Invoice WITH(UPDLOCK, HOLDLOCK)
WHERE LocName = 'A'
WAITFOR delay '00:00:10'
SET @i=@i + 1
INSERT INTO Invoice
VALUES ('A',
@i);
COMMIT
或者,您可以使用sp_getapplock
来序列化对该代码的访问。