2010-09-24 2 views
118

Фон: у меня есть критически важный запрос, который я бы хотел запустить, и мне неважно, грязные чтения.SQL Server NOLOCK и присоединяется

Мой вопрос: Если я использую объединения, должен ли я также указывать подсказку NOLOCK на них?

Например, является:

SELECT * FROM table1 a WITH (NOLOCK) 
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID 

Эквивалент:

SELECT * FROM table1 a WITH (NOLOCK) 
INNER JOIN table2 b ON a.ID = b.ID 

Или мне нужно указать (NOLOCK) намек на объединение, чтобы гарантировать, что я не запирая присоединяемой таблицы?

ответ

116

Я не адресую аргумент READ UNCOMMITTED, только ваш исходный вопрос.

Да, вам нужно WITH(NOLOCK) на каждой таблице соединения. Нет, ваши запросы не совпадают.

Попробуйте это упражнение. Начните транзакцию и вставьте строку в таблицу1 и таблицу2. Не совершайте и не откатывайте транзакцию.На этом этапе ваш первый запрос вернется успешно и включит незафиксированные строки; ваш второй запрос не будет возвращен, потому что table2 не имеет подсказки WITH(NOLOCK).

+1

спасибо за краткий ответ, именно то, что я искал в этом случае. – DanP

14

Я был уверен, что вам нужно указать NOLOCK для каждого JOIN в запросе. Но мой опыт был ограничен SQL Server 2005.

Когда я посмотрел MSDN только для подтверждения, я не мог найти ничего определенного. Приведенные ниже высказывания, кажется, заставляют меня думать, что за 2008 год, ваши два утверждения выше эквивалентны, хотя в 2005 году это не так:

[SQL Server 2008 R2]

Все блокировки подсказки распространяются на все таблицы и представления, которые являются доступными по тарифному плану, включая таблицы и представления, на которые делается ссылка в представлении. Кроме того, SQL Server выполняет соответствующие проверки согласованности блокировок.

[SQL Server 2005]

В SQL Server 2005, все блокировки подсказки распространяются на все таблицы и представления, на которые ссылаются в представлении. Кроме того, SQL Server выполняет соответствующие проверки согласованности блокировок.

Кроме того, следует отметить - и это относится к 2005 и 2008:

В таблице подсказки игнорируются, если таблица не доступна в плане запроса. Это может быть вызвано тем, что оптимизатор решил не обращаться к таблице вообще, или потому, что вместо этого обращается к индексированному виду. В последнем случае доступ к индексированному представлению может быть предотвращен с помощью подсказки запроса OPTION (EXPAND VIEWS).

+0

@ In Sane: Интересно ... спасибо за это ... Я полагаю, что я не навредил, включив его в JOINS, даже если это не совсем необходимо? Документация по NOLOCK довольно скудная, как вы уже упоминали; Мне не удалось найти что-то убедительное. – DanP

+2

@InSane: Откуда вы получили эту информацию? Кажется, это противоречит принятому ответу. –

+0

@notfed - ссылка на техническую ссылку http://technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - вы можете изменить версию базы данных сверху, чтобы сравнить одну и ту же статью для разных версий db – InSane

8

Ни то, ни другое. Вы устанавливаете уровень изоляции READ UNCOMMITTED, который всегда лучше, чем давать индивидуальные подсказки. Или, еще лучше, если вам нужны подробности, например consistency, используйте snapshot isolation.

+0

@Remus: Я не уверен, что могу использовать READ UNCOMMITTED в моем случае, потому что я получаю доступ к соединению через NHibernate для выполнения специального сырого вызова ADO.NET; может ли это быть указано inline в запросе или будет подчиняться уровню транзакции, присутствующему в транзакции NHibernate? – DanP

+0

Оберните вызов в 'using (TransactionScope scope = new TransactionScope (..., TransactionOptions) {...}' и установите «IsolationLevel» в параметрах: http://msdn.microsoft.com/en-us/ library/system.transactions.transactionoptions.isolationlevel.aspx –

+0

@Remus: К сожалению, управление транзакциями осуществляется на гораздо более высоком уровне, чем это, так что это тоже не вариант. – DanP

Смежные вопросы