Я не буду рассматривать READ UNCOMMITTEDспор, только ваш оригинальный вопрос.
Да, вам нужно WITH(NOLOCK)на каждом столе объединения. Нет, ваши запросы не совпадают.
Попробуйте это упражнение. Начните транзакцию и вставьте строку в table1 и table2. Не совершайте и не отменяйте транзакцию. В этот момент ваш первый запрос будет успешно возвращен и будет содержать незавершенные строки; Ваш второй запрос не вернется, потому что на table2 нет WITH(NOLOCK)подсказки.
Я был почти уверен, что вам нужно указать 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)подсказки запроса.
@ In Sane: Интересно ... спасибо за это ... Я предполагаю, что я не причинил вреда, включив его в JOINS, даже если это не совсем необходимо? Документация по NOLOCK довольно скудна, как вы уже упоминали; У меня были проблемы с поиском чего-либо убедительного.
ДанП
2
@ InSane: Откуда вы взяли эту информацию? Кажется, идет вразрез с принятым ответом.
Текст 2005 года говорит о ВЗГЛЯДАХ. Так что если вы делаете «из myview с (nolock)», то это говорит о том, что nolock распространяется на все таблицы и представления, участвующие в myview (у вас может быть 10 объединений). Не уверен, что именно означает текст 2008 года, поскольку он добавляет «доступ к плану запросов» в дополнение к представлениям.
Thierry_S
9
Ни. Вы устанавливаете уровень изоляции, READ UNCOMMITTEDкоторый всегда лучше, чем давать индивидуальные подсказки блокировки. Или, что еще лучше, если вам важны такие детали, как согласованность , используйте изоляцию моментальных снимков .
@Remus: я не уверен, что могу использовать READ UNCOMMITTED в моем случае, потому что я получаю доступ к соединению через NHibernate для выполнения специального необработанного вызова ADO.NET; это может быть указано в запросе inline или будет подчиняться уровню транзакции, присутствующему в транзакции NHibernate?
@Remus: К сожалению, управление транзакциями осуществляется на гораздо более высоком уровне, чем этот, так что это тоже не вариант.
ДанП
Понимаю. Затем, чтобы ответить на ваш вопрос: NOLOCK - это табличная подсказка, и как таковая она применяется к набору строк, к которому добавляется (таблица, представление, TVF и т. Д.). Если у вас есть несколько наборов строк, соединенных в запросе, каждый из них должен иметь свою собственную подсказку NOLOCK.
Ремус Русану
2
Но вы рассматривали изоляцию снимка? ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;, Результаты впечатляют, так как все обычные операции чтения с фиксацией превращаются в операции чтения снимков, без блокировки, но согласованные. Стоимость увеличенной tempdbнагрузки: msdn.microsoft.com/en-us/library/ms175492.aspx
Ни. Вы устанавливаете уровень изоляции,
READ UNCOMMITTED
который всегда лучше, чем давать индивидуальные подсказки блокировки. Или, что еще лучше, если вам важны такие детали, как согласованность , используйте изоляцию моментальных снимков .источник
using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}
и установитеIsolationLevel
параметры: msdn.microsoft.com/en-us/library/…ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;
, Результаты впечатляют, так как все обычные операции чтения с фиксацией превращаются в операции чтения снимков, без блокировки, но согласованные. Стоимость увеличеннойtempdb
нагрузки: msdn.microsoft.com/en-us/library/ms175492.aspx