Использование NOLOCK на столе, который соединяется с самим собой

Я работаю с ужасным представлением, которое внутренне объединяет множество таблиц, некоторые из которых являются одной и той же таблицей.

Мне интересно, когда стол соединяется с самим собой, как NOLOCK Подсказка интерпретируется, если это на одном из соединений, а не на другом? Это NOLOCK все еще действует на столе, или стол заблокирован вообще, если NOLOCK не входит в одно из объединений одной и той же таблицы?

Например (это псевдо-код, предположим, что есть действительные JOIN ON условия):

SELECT *
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK)
JOIN Table2_Table2 tt (NOLOCK)
JOIN Table2 t22 (NOLOCK)
JOIN Table1 t11

Есть ли Table1 запереть или остаться NOLOCKред?

3 ответа

Решение

Да, он заблокирован последним Table1 t11 вызов. Каждая подсказка блокировки таблицы применяется к конкретной ссылке. Если вы примените его только к одной из ссылок на таблицы, которая предназначена только для этой ссылки, а другие будут иметь свои собственные индивидуальные настройки блокировки. Вы можете проверить это используя BEGIN TRANSACTION и выполнить два разных запроса.

Запрос 1 (блокирует таблицу) Намеренно комментируя COMMIT TRANSACTION

BEGIN TRANSACTION
SELECT *
FROM Table1 WITH (TABLOCK)
-- COMMIT TRANSACTION

поскольку COMMIT TRANSACTION был закомментирован, транзакция не закрыта и будет по-прежнему удерживать блокировку. При выполнении второго запроса первая блокировка будет по-прежнему применяться к таблице из первого запроса.

Запрос 2 (этот запрос будет зависать из-за блокировки первой блокировки Table1 t11)

BEGIN TRANSACTION
SELECT *
FROM Table1 t1 (NOLOCK)
JOIN Table2 t2 (NOLOCK)
JOIN Table2_Table2 tt (NOLOCK)
JOIN Table2 t22 (NOLOCK)
JOIN Table1 t11
COMMIT TRANSACTION

Говоря очень упрощенно, подумайте об этом так: каждая таблица, на которую вы ссылаетесь в запросе, приводит к тому, что физический оператор плана выполнения обращается к этой таблице. Табличные подсказки применяются к этому оператору. Это означает, что вы можете иметь смешанные подсказки блокировки для одной и той же таблицы. Запрашиваемое вами поведение блокировки применяется к тем строкам, которые этот конкретный оператор читает. Соответствующий оператор может сканировать таблицу, или сканировать диапазон строк, или читать одну строку. Что бы это ни было, оно выполняется под указанными опциями блокировки.

Посмотрите на план выполнения вашего запроса, чтобы найти отдельных операторов.

Я предполагаю, что неиспользование nolock приведет к некоторому типу блокировки, независимо от того, будет ли он присоединен в другом месте запроса с помощью nolock. Таким образом, это может привести к блокировке строки, поэтому поместите nolock рядом с объединением, в котором оно отсутствует.

Другие вопросы по тегам