Гарантируется ли операция в SQL атомарной, если она выполняется в одном операторе обновления? - PullRequest
1 голос
/ 05 февраля 2010

Я пытаюсь устранить необходимость явной блокировки таблицы с помощью следующего кода, но из отчетов, которые я получаю, возможно, что параметр и значение в строке страдают от состояния гонки.

    Declare @NextNumber Int;

Update
    MyParameterTable
Set
    NextNumber = NextNumber + 1,
    @NextNumber = NextNumber + 1

Select @NextNumber As NextNumber;

Надеюсь, вы видите, что это просто увеличение целого числа и возвращение результата. У меня сложилось впечатление, что оператор обновления, отформатированный таким образом, будет обрабатывать необходимые блокировки, но, как я уже сказал, это может быть случай, когда параметр beign назначен вне блокировки обновления.

Может кто-нибудь пролить свет на это и предложить альтернативу?

Привет

Ryan

Ответы [ 2 ]

3 голосов
/ 05 февраля 2010

Это будет нормально блокироваться, но вы можете сделать это в выражении равенства из трех частей:

Declare @NextNumber Int;

Update
    MyParameterTable
Set
    @NextNumber = NextNumber = NextNumber + 1

Select @NextNumber As NextNumber;
1 голос
/ 06 февраля 2010

Я также понимаю, что в вашем запросе не будет проблем с расой или параллелизмом.

Я также думаю, что @Variable = Column = / Expression / - это просто синтаксический сахар поверх того же запроса, который вы первоначально разместили. Выполнение трассировки и проверка полученных и освобожденных замков докажут это окончательно.

Я не люблю использовать этот синтаксис, потому что он может иметь проблемы, как в следующем случае:

Update MyParameterTable
Set
   @NextNumber = NextNumber = NextNumber + 1,
   @NextNumber = @NextNumber + 1

Хотя я понимаю, что вы, возможно, никогда не захотите этого делать, но он ломается странным образом (первый ряд обрабатывается не так, как другие ряды), и это заставляет меня доверять ему. В какой-то момент в конкретном SP SQL 2000 были и настоящие ошибки с этим синтаксисом.

Если вы хотите убедиться, что ряд заблокирован правильно и не может возникнуть состояние гонки, то вот отличный способ проверить это. Откройте несколько окон запросов в SSMS / QA и в каждом из них сделайте следующее:

WAITFOR TIME '11:00:00' -- use a time in the near future
EXEC dbo.YourProcedureName

В результате все партии, представленные вами в разных сеансах, будут выполняться практически в один и тот же момент, что очень трудно смоделировать любым другим способом. Вскоре вы сможете получить четкий индикатор того, может ли возникнуть состояние гонки.

Я рекомендую вам несколько статей для дальнейшего чтения по этой теме. Они не об этой точной проблеме, но определенно связаны (имеют дело с условиями гонки во вставках и обновлениях):

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