Я знаю, что изоляция моментальных снимков исправит эту проблему, но мне интересно, безопасен ли 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, может ли он пойти не так в этом случае? Может ли он вернуться:
- Более одной строки, хотя я просил TOP 1?
- Нет строк, хотя одна существует и была зафиксирована?
- Хуже всего, строка, которая не удовлетворяет предложению WHERE?
Я много читал об этом в Интернете, но единственные репродукции аномалий с избыточным или недостаточным количеством, которые я видел ( one , two ), связаны с сканирования. Это включает только поиск. У Джеффа Этвуда есть пост об использовании NOLOCK, который вызвал хорошее обсуждение. Меня особенно заинтересовал комментарий Рика Таунсенда:
Во-вторых, если вы читаете грязные данные,
вы рискуете прочитать
совершенно неверный ряд Например, если
ваш выбор читает индекс, чтобы найти
ваша строка, то обновление изменяет
расположение строк (например, из-за
разделение страницы или обновление
кластерный индекс), когда ваш выбор
идет читать фактическую строку данных, это
либо там больше нет, либо другой
грести в целом!
Это возможно только со вставками и без обновлений? Если так, то я думаю, что даже мои поиски в таблице только для вставки могут быть опасными.
Обновление:
Я пытаюсь выяснить , как работает изоляция снимка . Похоже, что он основан на строках, где транзакции читают таблицу (без общей блокировки!), Находят интересующую их строку и проверяют, нужно ли им получить старую версию строки из хранилища версий в базе данных tempdb.
Но в моем случае ни в одной строке не будет более одной версии, поэтому хранилище версий кажется довольно бессмысленным. И если строка была найдена без общей блокировки, чем она отличается от использования NOLOCK?