В вашем сценарии я бы порекомендовал явно установить уровень изоляции для моментального снимка - это предотвратит чтение, препятствующее записи (вставкам и обновлениям), предотвращая блокировки, но эти чтения все равно будут "хорошими" чтениями (т.е. не грязные данные - это не то же самое, что NOLOCK)
Обычно я нахожу, что, когда у меня возникают проблемы с блокировкой моих запросов, я вручную контролирую примененную блокировку. например я бы делал обновления с блокировками на уровне строк, чтобы избежать блокировки на уровне страниц / таблиц, и устанавливал мои чтения на readpast (принимая, что я могу пропустить некоторые данные, в некоторых сценариях, которые могут быть в порядке)
ссылка | редактировать | удалить | флаг
РЕДАКТИРОВАТЬ - Объединение всех комментариев в ответ
В рамках процесса оптимизации сервер sql избегает получения подтвержденных чтений на странице, которая, как он знает, не изменилась, и автоматически возвращается к меньшей стратегии блокировки. В вашем случае, sql сервер переходит из сериализуемого чтения в повторяемое чтение.
В: Спасибо за полезную информацию о снижении уровней изоляции. Можете ли вы представить себе причину, по которой он будет использовать Serializable IsolationLevel в первую очередь, учитывая, что мы не используем явную транзакцию для SELECT - мы понимали, что неявная транзакция будет использовать ReadCommitted?
A: По умолчанию SQL Server будет использовать Read Commmited, если это ваш уровень изоляции по умолчанию, НО, если вы не дополнительно указываете стратегию блокировки в своем запросе, вы в основном говорите серверу sql «делай то, что считаешь лучшим, но я предпочитаю читать по коммиту ». Поскольку SQL Server свободен в выборе, он делает это для оптимизации запроса. (Алгоритм оптимизации в SQL Server очень сложен, и я не полностью понимаю его сам). Неявное выполнение транзакции не влияет на уровень изоляции, который использует сервер sql.
В: Последнее, кажется ли разумным, что SQL Server повысит уровень изоляции (и, вероятно, количество требуемых блокировок) для оптимизации запроса? Мне также интересно, повлияет ли на это повторное использование соединения в пуле, если оно унаследует последний использованный уровень изоляции?
A: Sql-сервер сделает это как часть процесса, называемого «Lock Escalation». От http://support.microsoft.com/kb/323630, я цитирую: «Microsoft SQL Server динамически определяет, когда выполнять эскалацию блокировок. При принятии этого решения SQL Server учитывает количество блокировок, удерживаемых при определенном сканировании, количество блокировок, которые удерживается всей транзакцией и памятью, которая используется для блокировок в системе в целом. Как правило, поведение SQL Server по умолчанию приводит к эскалации блокировок, возникающей только в тех точках, где это может повысить производительность или когда необходимо уменьшить чрезмерную блокировку системы памяти до более приемлемого уровня. Однако некоторые приложения или конструкции запросов могут вызывать эскалацию блокировки в тот момент, когда это нежелательно, и эскалация блокировки таблицы может блокировать других пользователей ".
Хотя эскалация блокировки - это не то же самое, что изменение уровня изоляции, под которой выполняется запрос, меня это удивляет, потому что я не ожидал, что сервер sql будет брать больше блокировок, чем позволяет уровень изоляции по умолчанию.