Пропускать намеки на блокировку строк, блокировку строк и блокировку при тестировании на наличие строки.
begin tran /* default read committed isolation level is fine */
if not exists (select * from Table with (updlock, rowlock, holdlock) where ...)
/* insert */
else
/* update */
commit /* locks are released here */
Подсказка при обновлении заставляет запрос принять блокировку обновления для строки, если она уже существует, не позволяя другим транзакциям изменять ее, пока вы не подтвердите или не откатитесь.
Подсказка удержания заставляет запрос принять блокировку диапазона, не позволяя другим транзакциям добавлять строку, соответствующую критериям вашего фильтра, пока вы не подтвердите или не откатитесь.
Подсказка о блокировке строки вынуждает детализацию блокировки на уровень строки вместо уровня страницы по умолчанию, поэтому ваша транзакция не будет блокировать другие транзакции, пытающиеся обновить несвязанные строки на той же странице (но помните о компромиссе между уменьшением конкуренции и увеличением накладные расходы на блокировку - вы должны избегать принятия большого количества блокировок на уровне строк в одной транзакции).
См. Http://msdn.microsoft.com/en-us/library/ms187373.aspx для получения дополнительной информации.
Обратите внимание, что блокировки воспринимаются как выполняемые операторы - вызов метода begin tran не дает вам иммунитета против другой транзакции, накладывающей блокировки на что-либо до того, как вы доберетесь до нее. Вы должны попытаться использовать свой SQL-код для удержания блокировок в кратчайшие сроки, совершая транзакцию как можно скорее (запоздайте поздно, выпустите раньше).
Обратите внимание, что блокировки на уровне строк могут быть менее эффективными, если ваш PK является bigint, так как внутреннее хеширование в SQL Server вырождено для 64-битных значений (разные значения ключа могут хешироваться с одним и тем же идентификатором блокировки).