Является ли READ UNCOMMITTED / NOLOCK безопасным в этой ситуации? - PullRequest
2 голосов
/ 09 июня 2010

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

У меня есть таблица, которая выглядит примерно так:

drop table Data

create table Data
(
    Id BIGINT NOT NULL,
    Date BIGINT NOT NULL,
    Value BIGINT,
    constraint Cx primary key (Date, Id)
)

create nonclustered index Ix on Data (Id, Date)

Нет обновлений в таблице, никогда. Удаление может происходить, но они никогда не должны конкурировать с SELECT, потому что они влияют на другой, более старый конец таблицы. Вставки выполняются регулярно, а разделение страниц на индекс (Id, Date) встречается крайне часто.

У меня тупиковая ситуация между стандартным INSERT и SELECT, которая выглядит следующим образом:

select top 1 Date, Value from Data where Id = @p0 order by Date desc

потому что INSERT получает блокировку на Cx (Date, Id; Value) и затем Ix (Id, Date), но SELECT получает блокировку на Ix (Id, Date) и затем Cx (Date, Id; Value) , Это связано с тем, что SELECT сначала выполняет поиск на Ix, а затем присоединяется к поиску на Cx.

Замена кластеризованного и некластеризованного индекса нарушит этот цикл, но это неприемлемое решение, поскольку оно будет вводить циклы с другими (более сложными) SELECT.

Если я добавлю NOLOCK в SELECT, может ли он пойти не так в этом случае? Может ли он вернуться:

  1. Более одной строки, хотя я просил TOP 1?
  2. Нет строк, хотя одна существует и была зафиксирована?
  3. Хуже всего, строка, которая не удовлетворяет предложению WHERE?

Я много читал об этом в Интернете, но единственные репродукции аномалий с избыточным или недостаточным количеством, которые я видел ( one , two ), связаны с сканирования. Это включает только поиск. У Джеффа Этвуда есть пост об использовании NOLOCK, который вызвал хорошее обсуждение. Меня особенно заинтересовал комментарий Рика Таунсенда:

Во-вторых, если вы читаете грязные данные, вы рискуете прочитать совершенно неверный ряд Например, если ваш выбор читает индекс, чтобы найти ваша строка, то обновление изменяет расположение строк (например, из-за разделение страницы или обновление кластерный индекс), когда ваш выбор идет читать фактическую строку данных, это либо там больше нет, либо другой грести в целом!

Это возможно только со вставками и без обновлений? Если так, то я думаю, что даже мои поиски в таблице только для вставки могут быть опасными.


Обновление:

Я пытаюсь выяснить , как работает изоляция снимка . Похоже, что он основан на строках, где транзакции читают таблицу (без общей блокировки!), Находят интересующую их строку и проверяют, нужно ли им получить старую версию строки из хранилища версий в базе данных tempdb.

Но в моем случае ни в одной строке не будет более одной версии, поэтому хранилище версий кажется довольно бессмысленным. И если строка была найдена без общей блокировки, чем она отличается от использования NOLOCK?

Ответы [ 2 ]

7 голосов
/ 09 июня 2010

Использование NOLOCK или READ UNCOMMITTED означает, что вы отказываетесь от какой-либо гарантии согласованности.Точка.

Если вам нужна последовательность, не делайте грязных чтений.Все ваше объяснение основано на недокументированном поведении, которое может измениться в будущих выпусках, и, что еще хуже, на определенных планах доступа , ожидаемых для вашего запроса.Оптимизатор запросов может свободно выбирать любой план, который сочтет нужным, и любые предположения, которые вы делаете, могут быть сорваны в процессе производства.Итак, вернемся к исходной точке: не делайте грязного чтения, если вы не готовы к последствиям.

Не уверен, что это применимо, не ясно, чего вы пытаетесь достичь с помощью своего запроса / таблицы,но, возможно, эта статья может помочь: Использование таблиц в качестве очередей .

Обновлено
Где чтение NOLOCK будет считывать несовместимое состояние (например, читать устаревшее неключ кластеризованного индекса и преследовать его до отсутствующей строки в кластеризованном индексе) при считывании моментального снимка будет найдена «отсутствующая» строка в хранилище версий.Для стабильных данных чтение снимка идентично чтению nolock.Волшебство хранилища версий вступает в игру всякий раз, когда данные изменяются (незафиксированные обновления), потому что считанные снимки попадают в хранилище версий и находят «старые» значения (стабильные и согласованные), при которых считывание nolock превращается в бесполезные и преследующие указатели вЛала Лэнд.

1 голос
/ 09 июня 2010

В этом случае вы должны быть в безопасности с NOLOCK. Еще одна мысль: добавление значения в качестве включенного столбца в индексе Ix должно устранить поиск по Cx.

create nonclustered index Ix on Data (Id, Date) include (Value)
...