SQL Server ROWLOCK через SELECT, если не существует транзакции INSERT

Я обновился с SQL Server 2005 до 2008. Я помню, что в 2005 году ROWLOCK просто не работал, и мне приходилось использовать PAGELOCK или XLOCK для достижения любого типа фактической блокировки. Я знаю, что читатель этого спросит: «Что ты сделал не так?» Ничего такого. Я убедительно доказал, что могу редактировать строку «ROWLOCKED», но не могу, если повыслю уровень блокировки. У меня не было возможности проверить, работает ли это в SQL 2008. Мой первый вопрос: кто-нибудь сталкивался с этой проблемой в 2008 году?

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

Чтобы проиллюстрировать принцип, будет ли работать следующий код?

BEGIN TRAN

SELECT      ProfileID
FROM        dbo.UseSessions
WITH        (ROWLOCK)
WHERE       (ProfileID = @ProfileID)
OPTION      (OPTIMIZE FOR (@ProfileID UNKNOWN))

if @@ROWCOUNT = 0 begin
    INSERT INTO dbo.UserSessions (ProfileID, SessionID)
    VALUES      (@ProfileID, @SessionID)
end else begin
    UPDATE      dbo.UserSessions
    SET         SessionID = @SessionID, Created = GETDATE()
    WHERE       (ProfileID = @ProfileID)
end

COMMIT TRAN

person IamIC    schedule 02.12.2010    source источник
comment
По какой причине вы не можете использовать MERGE (technet.microsoft.com/en -us/library/bb510625.aspx)?   -  person Ed Harper    schedule 02.12.2010
comment
Спасибо @Эд. Я понятия не имел, что существует команда. Это отвечает на вопрос.   -  person IamIC    schedule 02.12.2010
comment
Хорошо, это была моя ошибка. Конечно.   -  person IamIC    schedule 03.12.2010
comment
@Ed, MERGE по-прежнему понадобятся те же подсказки для таблиц, что и код, который я написал.   -  person IamIC    schedule 03.12.2010
comment
Ваш код будет работать только в сериализуемом режиме изоляции транзакций, иначе ничто не остановит другой процесс, выполняющий вставку между вашим выбором и вашей вставкой.   -  person Chris KL    schedule 10.03.2015


Ответы (1)


Объяснение...

  • ROWLOCK/PAGELOCK — это степень детализации
  • XLOCK это режим

Степень детализации, уровень изоляции и режим ортогональны.

  • Детализация = что заблокировано = строка, страница, таблица (PAGLOCK, ROWLOCK, TABLOCK)

  • Уровень изоляции = продолжительность блокировки, параллелизм (HOLDLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE)

  • Режим = совместное использование/эксклюзивность (UPDLOCK, XLOCK)

  • "комбинированный", например NOLOCK, TABLOCKX

XLOCK заблокировал бы строку исключительно так, как вы хотите. ROWLOCK/PAGELOCK не будет.

person gbn    schedule 02.12.2010
comment
Спасибо @gbn. Так что WITH (XLOCK, ROWLOCK) поможет :) - person IamIC; 03.12.2010
comment
как ни странно, WITH (PAGELOCK) заблокировал строку. Из того, что вы говорите, я не знаю, почему это произошло. - person IamIC; 06.09.2012
comment
@IanC нет, это определенно не поможет - прочитайте мой ответ выше :) - person Chris KL; 10.03.2015