Если кто-то скажет, что без NOLOCK его приложение всегда будет заблокировано, то (скорее всего) возникнет проблема с его запросами. взаимоблокировка означает, что две транзакции не могут быть выполнены из-за конфликта ресурсов и проблема не может быть решена.Пример:
Рассмотрим транзакции A и B. Оба находятся в полете.Транзакция A вставила строку в таблицу X, а транзакция B вставила строку в таблицу Y, поэтому транзакция A имеет эксклюзивную блокировку X, а транзакция B - эксклюзивную блокировку Y.
Теперь, транзакция A нуждаетсявыполнить SELECT для таблицы Y, а транзакция B должна выполнить SELECT для таблицы X.
Две транзакции заблокированы: A требуется ресурс Y, а B нужен ресурс X. Поскольку ни одна транзакция не может продолжаться, пока другая не завершится,Ситуация не может быть решена: ни одна транзакция не требует удовлетворения для ресурса, пока другая транзакция не снимет свою блокировку с ресурса в конфликте (либо ROLLBACK, либо COMMIT, не имеет значения.)
SQL Server определяет этоВ этом случае выберите одну или другую транзакцию в качестве жертвы тупика, прервите эту транзакцию и откатитесь, оставив другую транзакцию свободной, чтобы приступить к ее предполагаемому завершению.
В реальной жизни взаимоблокировки редки (IMHO).Один исправляет их с помощью
- , гарантируя, что область транзакции настолько мала, насколько это возможно, что делает SQL-сервер автоматически (область транзакции SQL Server по умолчанию представляет собой один оператор с неявным COMMIT), и
- обеспечение доступа транзакций к ресурсам в одинаковой последовательности.В приведенном выше примере, если транзакции A и B заблокировали ресурсы X и Y в одной и той же последовательности, тупиковая ситуация не возникнет.
Таймауты
Тайм-аут, с другой стороны, возникает, когда транзакция превышает время ожидания и откатывается из-за конфликта ресурсов.Например, Транзакции A необходим ресурс X. Ресурс X заблокирован Транзакцией B, поэтому Транзакция A ожидает снятия блокировки.Если блокировка не снята в течение срока ожидания запросов, ожидающая транзакция отменяется и откатывается.С каждым запросом связан тайм-аут запроса (по-моему, значение по умолчанию - 30 с), после которого транзакция прерывается и откатывается.Тайм-аут запроса может быть установлен равным 0 с, и в этом случае SQL Server будет ждать запрос вечно.
Это, вероятно, то, о чем они говорят.По моему опыту, такие таймауты обычно происходят в больших базах данных, когда большие пакетные задания обновляют тысячи и тысячи записей в одной транзакции, хотя они могут происходить из-за того, что транзакция выполняется слишком долго (подключитесь к вашей производственной базе данных в Query Abalyzer, выполните BEGINTRANSACTION, обновите одну строку в часто используемой таблице в Query Analyzer и перейдите на ланч, не выполняя ROLLBACK или COMMIT TRANSACTION, и посмотрите, сколько времени понадобится рабочим администраторам баз данных для вас. Не спрашивайте меня, как язнайте это)
Этот тайм-аут обычно приводит к тому, что разбрызгивание совершенно невинного SQL со всеми видами подсказок NOLOCK
[ СОВЕТ: если вы собираетесь это сделать,просто выполните команду SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED в качестве первого оператора в вашей хранимой процедуре и покончили с ним.]
Проблема этого подхода (NOLOCK / READ UNCOMMITTED) заключается в том, что вы можете читать незафиксированные данные из другой транзакции: вещи, которые есть взавершено или может откатиться позже, поэтому ваша целостность данных подвергается риску.Возможно, вы отправляете счет на основе данных с высоким уровнем надуманности.
Мое общее правило заключается в том, что следует избегать использования табличных подсказок, насколько это возможно.Пусть SQL Server и его оптимизатор запросов выполняют свою работу.
Правильный способ избежать такого рода проблем - избежать таких транзакций (например, вставить миллион строк одним махом), которые вызывают проблемы. Стратегия блокировки, заложенная в реляционную базу данных SQL, разработана для небольших транзакций с коротким объемом. Замок должен быть небольшим по объему и коротким по продолжительности. Подумайте: «Банковский кассир обновляет чей-то текущий счет с помощью депозита». в качестве основного варианта использования. Спроектируйте свои процессы так, чтобы они работали в этой модели, и вы всегда будете намного счастливее.
Вместо вставки миллиона строк в одном операторе mondo insert выполняйте работу в независимых чанках и фиксируйте каждый чанк независимо. Если ваша миллионная вставка строки умирает после обработки 999 000 строк, вся выполненная работа теряется (не говоря уже о том, что откат может быть почти равен *, и таблица все еще заблокирована во время отката). Если вы вставите миллион строк в блок из 1000 строк каждая, фиксируясь после каждого блока, вы избегаете конфликта блокировок, который вызывает взаимные блокировки, так как блокировки будут получены и сняты, и все будет продолжать двигаться. Если что-то идет на юг в 999-м блоке из 1000 строк, и транзакция прерывается и откатывается, вы все равно вставили 998 000 строк; вы потеряли только 1000 строк работы. Перезапустить / Повторить намного проще.
Кроме того, повышение блокировки происходит в больших транзакциях. Для эффективности блокировки увеличиваются в размерах с увеличением количества блокировок, удерживаемых транзакцией. Если одна транзакция вставляет / обновляет / удаляет одну строку в таблице, я получаю блокировку строки. Продолжайте делать это, и как только число блокировок строк, удерживаемых этой транзакцией для этой таблицы, достигнет порогового значения, SQL Server расширит стратегию блокировок: блокировки строк будут объединены и преобразованы в блокировку страниц меньшего числа, что увеличит объем замки держались. С этого момента вставка / удаление / обновление одной строки заблокирует эту страницу в таблице. Как только количество удерживаемых блокировок страниц достигает порогового значения, блокировки страниц снова консолидируются, и стратегия блокировок перерастает в блокировки таблиц: транзакция теперь блокирует всю таблицу, и никто больше не может играть до тех пор, пока транзакция не завершится или не откатится.
Возможность функционально избежать использования NOLOCK / READ UNCOMMITTED полностью зависит от характера процессов, затрагивающих базовую базу данных (и культуры организации, которой она принадлежит).
Сам я стараюсь максимально избегать его использования.
Надеюсь, это поможет.