4

У меня есть две тестовые транзакции в течение двух сеансов соответственно. Предполагая, что эти две транзакции будут выполняться одновременно. Я пытаюсь сделать так, чтобы одна транзакция вставляла номер счета правильно после выполнения другой транзакции. Нет дубликатов. Я сделал это, как показано ниже. Но если я удалю с (tablockx) в сеансе 2, они больше не будут работать. Я проверил в строке книги, но не ответил. Кто-нибудь поможет? Serializable не будет работать, поскольку два 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 гарантирует, что две одновременные транзакции не могут содержать одну и ту же блокировку, но, в отличие от эксклюзивной, не блокируют другие (нормальные) считыватели, которые не используют подсказку.

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» –

Смежные вопросы