Тупик при запросе, который выполняется одновременно - PullRequest
2 голосов
/ 13 апреля 2011

У меня есть хранимая процедура, которая выполняет следующее (упрощенно):

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

Моя проблема заключается в том, что, когда два или более пользователей выполняют это одновременно, я получаю взаимоблокировки.Теперь, как я понимаю, в тот момент, когда я делаю свой первый выбор в процедуре, это должно создать блокировку в tbl.Если вторая процедура затем вызывается, пока первая процедура еще выполняется, она должна дождаться ее завершения, верно?

В настоящий момент это вызывает тупик, есть идеи?

Ответы [ 2 ]

3 голосов
/ 13 апреля 2011

Для запроса insert требуется блокировка, отличная от select.Блокировка для select блокирует секунду insert, но не блокирует секунду select.Таким образом, оба запроса могут начинаться с select, но оба они блокируют на insert.

другого. Это можно решить, попросив первый запрос заблокировать всю таблицу:

SET @intNo = (SELECT MAX(intNo) + 1 FROM tbl with (tablockx))
                                             ^^^^^^^^^^^^^^^

Это заставит вторую транзакцию select ждать завершения первой транзакции.

1 голос
/ 13 апреля 2011

Упростите, чтобы у вас была одна выписка, а транзакции нет

--BEGIN TRANSACTION  not needed

INSERT INTO tbl(intNo)
OUTPUT INSERTED.intNo
SELECT MAX(intNo) + 1 FROM tbl WITH (TABLOCK)

--COMMIT TRANSACTION not needed

Хотя, почему вы не используете IDENTITY ...?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...