Использование 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 рядом с объединением, в котором оно отсутствует.