4

我在兩個會話中分別有兩個測試事務。假設這兩個事務將同時運行。我試圖做的是讓一個事務在其他事務完成後正確插入發票號碼。沒有重複。我做了如下。但是,如果我在第2節中用(tablockx)刪除它們,它們將不再工作。我檢查了在線書,但沒有回答。任何人都會幫忙?可串行化將不起作用,因爲兩個SELECT在這裏想要互相排斥。謝謝。是否必須在每個會話中指定tablockx?

在會議1:

begin transaction 
    declare @i int 
    select @i=MAX(InvNumber) from Invoice 
    with(tablockx) 
    where LocName='A' 
    waitfor delay '00:00:10' 
    set @[email protected]+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 @[email protected]+1 
    insert into Invoice values('A',@i); 
commit 

回答

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 @[email protected] + 1 

INSERT INTO Invoice 
VALUES  ('A', 
      @i); 

COMMIT 

或者你可以只使用sp_getapplock能夠連續訪問代碼。

+0

(UPDLOCK,HOLDLOCK)不起作用,因爲爲兩個會話生成相同的發票號碼。 – FebWind

+0

@FebWind - 如果你在交易中運行它作爲我的答案,這是不可能的。 'HOLDLOCK'總是至少鎖定查詢指定的整個範圍,並且兩個併發事務不可能在同一個資源上有'UPDLOCK'。 –

+0

@FebWind - 這在SSMS中很容易看到。只需打開兩個窗口。並在'BEGIN TRANSACTION DECLARE @i INT SELECT @i = MAX(InvNumber)FROM Invoice WITH(UPDLOCK,HOLDLOCK)WHERE LocName ='A''中執行以下內容:第二個事務將被阻止「正在執行查詢」等待第一個直到你回到第一個窗口並執行「COMMIT」或「ROLLBACK」 –

相關問題