Пропускать подсказки при обновлении, блокировке строки и блокировке при проверке наличия строки.
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 trans не дает вам иммунитета против другой транзакции, которая блокирует блокировки до того, как вы к ней попадете. Вы должны попытаться использовать свой SQL-код для удержания блокировок в кратчайшие сроки, зафиксировав транзакцию как можно скорее (запоздайте поздно, отпустите раньше).
Обратите внимание, что блокировки на уровне строк могут быть менее эффективными, если ваш PK является bigint, поскольку внутреннее хеширование в SQL Server вырождено для 64-битных значений (разные значения ключа могут хешироваться для одного и того же идентификатора блокировки).