Я нахожусь в тупиковой ситуации со старой версией одного из наших программ по одному и тому же хранимой процедуре, которая в основном выполнялась одновременно двумя разными пользователями.
Запрос 1:
UPDATE [UserExport].[Stat] WITH (ROWLOCK)
SET BOKey = CustomerID + '|' + ISNULL(Period, '') + '|' + ISNULL(FECode, '')
WHERE CompanyCode = '001' AND BOKey IS NULL AND UserCode = '53'
Запрос 2:
UPDATE [UserExport].[Stat] WITH (ROWLOCK)
SET BOKey = CustomerID + '|' + ISNULL(Period, '') + '|' + ISNULL(FECode, '')
WHERE CompanyCode = '001' AND BOKey IS NULL AND UserCode = '87'
Вывод SQL Profiler (только для версии ridlock)
<ridlock fileid="3" pageid="55475" dbid="7" objectname="PRTE.UserExport.Stat" id="lock1b722b980" mode="X" associatedObjectId="72057594355384320">
<owner-list>
<owner id="process4a9708" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process55d4c8" mode="U" requestType="wait"/>
</waiter-list>
</ridlock>
<ridlock fileid="3" pageid="155604" dbid="7" objectname="PRTE.UserExport.Stat" id="lock1b7999580" mode="X" associatedObjectId="72057594355384320">
<owner-list>
<owner id="process55d4c8" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process4a9708" mode="U" requestType="wait"/>
</waiter-list>
</ridlock>
Мы выполняем это на SQL Server 2008 R2, схема UserExport используется в качестве зеркала dbo для хранения данных, которые нужно экспортировать, и ни одна из ее таблиц не имеет индексов или триггеров.
Я знаю, что дизайн плохой, на самом деле он был переписан в будущих версиях, как и должно быть, однако я все еще не понимаю, как может произойти взаимоблокировка на RID, так как оба запроса не обновляли одну и ту же строку.
Я прочитал здесь , что оператор UPDATE с подсказкой ROWLOCK может заблокировать больше строк, чем он фактически обновляет при работе с таблицей без индекса, поскольку он также блокирует другие строки чтения, но я не могу найти любое дальнейшее объяснение или способ справиться с ним, только обновив запрос.
Означает ли это, что ОБНОВЛЕНИЕ таблицы без индекса всегда так рискованно?
Или, может быть, я что-то неправильно понял, и есть способ гарантировать блокировку только обновленных строк?