Що таке "with (nolock)" у SQL Server?


610

Чи може хтось пояснити наслідки використання with (nolock)запитів, коли ви повинні / не повинні його використовувати?

Наприклад, якщо у вас є банківська програма із високими ставками транзакцій та великою кількістю даних у певних таблицях, у яких типах запитів не було б у порядку блокування? Чи бувають випадки, коли ви завжди повинні його використовувати / ніколи не використовувати?



1
одне посилання тут - mssqltips.com/sqlservertip/2470/…
Steam

1
Ось чудовий підсумок наслідків використання NOLOCK blogs.msdn.com/b/davidlean/archive/2009/04/06/…
Брайан

Відповіді:


461

З (НОЛОК) - еквівалент використання ПРОЧИТАТИ НЕЗАБАВЛЕНО як рівня ізоляції транзакцій. Отже, ви ризикуєте прочитати незапущений рядок, який згодом повертається назад, тобто дані, які ніколи не вносили його в базу даних. Отже, хоча це може запобігти затримці читання в інших операціях, це ризикує. У банківській програмі з високими ставками транзакцій, мабуть, це не буде правильним рішенням будь-якої проблеми, яку ви намагаєтеся вирішити з цим IMHO.


156
Більшість банківських додатків можуть безпечно користуватися nolock, оскільки вони є транзакційними в діловому сенсі. Ви пишете лише нові рядки, ви ніколи їх не оновлюєте.
Джонатан Аллен

49
@ Grauenwolf - Вставлений, але незапущений рядок все ще може призвести до брудних читань.
saasman

16
@ Saasman - Якщо ви ніколи не здійснюєте відкатних транзакцій, це не має значення. А при таблиці, що містить лише вставки, шанси на відкат невеликі. І якщо вони все-таки відбудуться, ви все одно виправите це у звіті про відхилення в кінці дня.
Джонатан Аллен

1
Я закріпився. Я припускаю, що додавання не блокує натяків на. Для прикладу:
Росс Буш,

11
Якщо ви користуєтесь NOLOCKa, SELECTви ризикуєте повернути одні й ті ж рядки більше одного разу (дублюються дані), якщо дані коли-небудь вставляються (або оновлюються) в таблицю під час вибору.
Ян Бойд

170

Питання в тому, що гірше:

  • тупик, або
  • неправильне значення?

Для фінансових баз даних тупики набагато гірші за неправильні значення. Я знаю, що це звучить назад, але вислухай мене. Традиційний приклад транзакцій БД - це оновлення двох рядків, віднімання від одного і додавання до іншого. Це неправильно.

У фінансовій базі даних ви використовуєте господарські операції. Це означає додавати по одному рядку до кожного облікового запису. Надзвичайно важливо, щоб ці транзакції завершились і рядки були успішно записані.

Отримати тимчасово невірно баланс рахунку - це не велика справа, саме для цього потрібно узгодити кінець дня. А перевищення рахунку з рахунку набагато частіше трапляється через те, що два банкомати використовуються одразу, ніж через неможливе читання з бази даних.

Однак, SQL Server 2005 виправляв більшість помилок, які зробили NOLOCKнеобхідними. Тому, якщо ви не використовуєте SQL Server 2000 або новішої версії, вам це не потрібно.

Подальше читання
версій на рівні рядків


22
Отримати тимчасово неправильний баланс рахунку - це не велика справа? Що робити, якщо ця операція - це та, де ви знімаєте готівку з банкомату без обмеження на овердрафт?
Навчання

13
@Навчання: Що станеться, якщо ви виймете гроші за 30 секунд до того, як хтось стягне з вашої картки? Поки все спілкування не буде по-справжньому неміцним, овердрафти стануть фактом життя.
Джонатан Аллен

6
+1 У фінансовій програмі (скрізь, не тільки в банках) немає ні оновлень, ні видалень. Навіть неправильні операції виправляються вставкою записів. Що таке термін англійською мовою? Це "штормо"? Google не допоміг мені відповісти на це запитання
Геннадій Ванін Геннадій Ванин

7
Пізній вхід ... тупики слід спіймати та повторити спробу. Брудні читання мають наслідки
gbn

4
@JonathanAllen просто fyi, термін - UTmost, а не UP.
Джиммі Д

57

На жаль, справа не лише в тому, щоб прочитати невідомі дані. У фоновому режимі ви можете прочитати сторінки двічі (у випадку розбиття сторінки) або взагалі пропустити сторінки. Тож ваші результати можуть бути сильно перекошеними.

Перегляньте статтю Іціка Бен-Гана . Ось уривок:

"За допомогою підказки NOLOCK (або встановлення рівня ізоляції сеансу ПРОЧИТАТИ НЕЗАКОМНО) ви говорите SQL Server, що ви не очікуєте послідовності, тому жодних гарантій немає. Майте на увазі, що" непослідовні дані "не означає лише, що Ви можете побачити незапропоновані зміни, які згодом були повернуті назад, або зміни даних в проміжному стані транзакції. Це також означає, що в простому запиті, який сканує всі дані таблиці / індексу SQL Server, можуть втратити позицію сканування або ви можете закінчитись отримання одного і того ж ряду двічі ".


5
Трохи далі він пояснює, як отримати той самий рядок двічі: я відтворять таблицю T1 таким чином, що кластерний індекс на col1 буде визначений як унікальний індекс з опцією IGNORE_DUP_KEY. Це означає, що дублікати значень не можуть існувати в col1, а також, що спроба вставити повторюваний ключ не призведе до невдачі транзакції і генерує помилку, а просто генерує попередження. Якщо ви не використовуєте цей дивний варіант, вам, ймовірно, не доведеться турбуватися про отримання рядків двічі
JanHudecek

Ви все одно можете отримати одинарні рядки навіть без дротового варіанту - якщо ваш запит використовує, наприклад, не унікальний індекс. Це не унікально для блокування.
RMD

54

Приклад підручника для законного використання підказки про блокування - вибірки звітів проти високооновлюваної бази даних OLTP.

Щоб взяти актуальний приклад. Якщо великий американський банк з високими вулицями хотів би скласти погодинний звіт, шукаючи перші ознаки проходження міського рівня на банку, запит на блокування міг би сканувати таблиці транзакцій, підсумовуючи грошові депозити та зняття грошових коштів на місто. Для такого звіту невеликий відсоток помилок, спричинений транзакціями з оновленим оновленням, не зменшить значення звіту.


31

Не впевнені, чому ви не обертаєте фінансові трансакції в транзакціях з базами даних (як, наприклад, при переказі коштів з одного рахунку на інший - ви не здійснюєте одночасно одну сторону транзакції - саме тому існують явні транзакції). Навіть якщо ваш код наголошується на бізнес-транзакціях, як це здається, всі транзакційні бази даних можуть робити неявні зворотні звороти у випадку помилок чи збоїв. Я думаю, що це обговорення перевершило вашу голову.

Якщо у вас виникають проблеми із блокуванням, застосуйте версію та очистіть код.

Жоден замок не тільки повертає неправильні значення, він повертає фантомні записи та дублікати.

Поширена помилкова думка, що вона завжди робить запити швидшими. Якщо на столі немає блоків запису, це не має ніякого значення. Якщо на столі є замки, це може зробити запит швидше, але є причина, що в основному були винайдені замки.

Справедливо кажучи, ось два особливих сценарії, коли натяк на блокування може забезпечити корисність

1) Серверна база даних до 2005 р., Якій потрібно виконувати довгий запит проти живої бази даних OLTP, це може бути єдиним способом

2) Погано написана програма, яка блокує записи та повертає контроль до інтерфейсу користувача та читачів, безстроково блокується. Тут може бути корисним Nolock, якщо додаток неможливо виправити (сторонні програми тощо), а база даних - до 2005 року, або версія версії не може бути включена.


11
Я згоден з вами, що NOLOCK не слід використовувати для компенсації погано написаного коду. Однак я вважаю, що ваша атака Джонатана є невиправданою, оскільки він ніколи фактично не згадував транзакції бази даних . Він просто вказував, що фінансові програми, як правило, не дозволяють редагувати записи (очевидно, є деякі винятки). У прикладі переказу коштів він говорить, що було б дивним, якби ви мутували значення балансу рахунку замість того, щоб додавати дебетовий / кредитний запис до великої книги.
chrnola

19
Коли гроші, перераховані з одного рахунку на інший у різних банках, як ви вважаєте, що відбувається? Якась база даних uber бере блокування на стіл у Банку Америки, а інша у Wells Fargo? Ні. Фінансова транзакція записується до кожного, а потім процес наприкінці дня підтверджує, що всі записи збігаються.
Джонатан Аллен

24

NOLOCKеквівалентно READ UNCOMMITTED, однак Microsoft каже, що ви не повинні використовувати це для UPDATEабо DELETEтверджень:

Для операторів UPDATE або DELETE: Ця функція буде видалена в майбутній версії Microsoft SQL Server. Уникайте використання цієї функції в нових роботах з розробки та плануйте змінювати додатки, які зараз використовують цю функцію.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Ця стаття стосується SQL Server 2005, тому підтримка NOLOCKіснує, якщо ви використовуєте цю версію. Для того, щоб в майбутньому ви кодували код (якщо ви вирішили використовувати брудні читання), ви можете використовувати це у своїх збережених процедурах:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


21

Ви можете використовувати його, коли ви лише читаєте дані, і вам не дуже важливо, отримуєте чи не повертаєтесь дані, які ще не здійснені.

Це може бути швидше в процесі читання, але я не можу реально сказати на скільки.

Взагалі я рекомендую не використовувати його - читання невідомих даних у кращому випадку може бути трохи заплутаним.


1
Було б добре, якби ви згадали той факт, що SQL Server 2005 має версію версій, тому блоківки вже не потрібні.
Джонатан Аллен

Що ж, "з (nolock)" все ще має своє місце навіть у SQL Server 2005 - але переваги стають стрункішими та стрункішими, це правда.
marc_s

18

Інший випадок, коли зазвичай це нормально - це база даних звітів, де дані, можливо, вже постаріли, а записи просто не бувають. Однак у цьому випадку адміністратор повинен встановити параметр на рівні бази даних або таблиці шляхом зміни рівня ізоляції за замовчуванням.

У загальному випадку ви можете використовувати його , коли ви дуже впевнені , що це нормально читати старі дані. Важливо пам’ятати, що дуже легко зрозуміти це неправильно . Наприклад, навіть якщо під час написання запиту це нормально, ви впевнені, що в майбутньому щось не зміниться в базі даних, щоб зробити ці оновлення важливішими?

Я також 2-го поняття, що це, мабуть, не дуже гарна ідея в банківському додатку. Або додаток для інвентаризації. Або де б ви не думали про транзакції.


4
Як людина, яка працює над банківськими додатками, я мушу сказати, що «блокування» не є проблемою. Записи транзакцій, тобто рядки, які вставляються, але ніколи не оновлюються та не видаляються, напрочуд стійкі до проблем читання невпорядкованих даних.
Джонатан Аллен

15

Проста відповідь - щоразу, коли ваш SQL не змінює дані, і у вас є запит, який може заважати іншій діяльності (за допомогою блокування).

Варто розглянути будь-які запити, які використовуються для звітів, особливо якщо запит займає більше, ніж, скажімо, 1 секунди.

Це особливо корисно, якщо у вас є звіти типу OLAP, які ви працюєте з базою даних OLTP.

Перше питання, яке потрібно задати - це "чому я переживаю з цього приводу?" За моїм досвідом, помилка поведінки за замовчуванням часто відбувається, коли хтось перебуває в режимі "спробувати все", і це один випадок, коли несподівані наслідки малоймовірні. Занадто часто це справа передчасної оптимізації, і вона може надто легко вбудовуватися у додаток «на всякий випадок». Важливо зрозуміти, чому ви це робите, яку проблему вирішує та чи є у вас насправді проблема.


11

Коротка відповідь:

Використовуйте WITH (NOLOCK)в операторі SELECT лише таблиці, що мають кластерний індекс.

Довга відповідь:

З (NOLOCK) часто використовується як магічний спосіб прискорити читання бази даних.

Набір результатів може містити рядки, які ще не були здійснені, які часто згодом повертаються назад.

Якщо З (NOLOCK) застосовується до таблиці з некластеризованим індексом, то індекси рядків можуть бути змінені іншими транзакціями, оскільки дані рядків передаються в таблицю результатів. Це означає, що в наборі результатів можуть бути відсутні рядки або відображати один і той же ряд кілька разів.

ЧИТАЙТЕ ЗАВАНТАЖЕНО додає додатковий випуск, коли дані пошкоджуються в одному стовпчику, де кілька користувачів змінюють одну і ту ж клітинку одночасно.


2
Читання недозволених даних є прийнятним, якщо це не змінює остаточне рішення. Наприклад, якщо ви намагаєтеся спроектувати, скільки грошей збирається заробити ваш роздрібний магазин протягом наступних 6 місяців, побачивши, що Таммі купила 2 рулони паперових рушників, коли вона дійсно купила 3, не змінить вашу думку про майбутнє .
Джонатан Аллен

1
Якщо ваш фільтр включає зараз, ваші дані будуть неточними в момент запуску запиту. Якщо ваш фільтр містить лише історичні дані, його використання READ UNCOMITTED взагалі не вплине на нього. Є причина, чому вона була включена до стандарту ANSI.
Джонатан Аллен

2
Ніколи не кажи ніколи. Якщо ви ПОТРІБНІ, щоб дані були на 100% точними, тоді вам не слід використовувати замок Для мене, як правило, це не так. Під час подання даних користувачеві, до моменту їх дії, вони, можливо, вже змінилися, але, швидше за все, цього не зробили, і твердження про блокування не варто затримувати відповідь.
Перпостерер

Давайте дотримуватись систем, гідних існування. Не забувайте, що у Таммі ідеально пристойний мозок, тому використовувати базу даних для запису мініатюрних покупок паперового рушника, про які ніхто не звертає уваги, в кращому випадку є безглуздим. Ми зосереджуємось на важливих системах, наприклад, отримуючи людям своєчасну оплату, реагуючи на надзвичайні ситуації тощо. Важливою є користь, коли використання З (НОЛОК) розуміється людьми, які програмують будь-яку систему, гідну існування. Коли людина може зробити кращу роботу, ніж база даних, тоді подумайте про перестановку цих ресурсів.
WonderWorker

10

Мої 2 копійки - це має сенс використовувати WITH (NOLOCK), коли потрібно генерувати звіти. На даний момент дані не сильно змінюються, і ви не хочете блокувати ці записи.


2
Я думаю, що З (NoLOCK) краще, якщо вам не байдужі поточні зміни.
Абдул Сабур

9

Якщо ви обробляєте фінансові операції, ви ніколи не захочете їх використовувати nolock. nolockнайкраще використовувати для вибору з великих таблиць, у яких є безліч оновлень, і вам не байдуже, чи отримана вами запис може бути застарілою.

Для фінансових записів (і майже всіх інших записів у більшості застосунків) це nolockможе спричинити загрозу, оскільки ви потенційно можете прочитати дані із запису, до якого записувались, і не отримати правильних даних.


5
Дивно, але при роботі з фінансовими даними це не проблема. Оскільки рядки ніколи не редагуються, а облікові записи вирівнюються в кінці дня, читання тимчасово неправдивих даних нічого не робить.
Джонатан Аллен

8

Я звик отримувати "наступну партію" для справ. У цьому випадку не має значення, який саме товар, і я маю багато користувачів, які виконують цей самий запит.


1
Ми робимо щось подібне, щоб подати фонове завдання з чергою роботи, яку потрібно виконати. Якщо, потрапляючи на певний запис, його більше немає / відповідає критеріям відбору, він просто переходить до наступного.
TripeHound

7

Використовуйте блокування, коли ви добре з "брудними" даними. Це означає, що nolock може також читати дані, які перебувають у процесі зміни та / або непідтверджених даних.

Зазвичай це не дуже гарна ідея використовувати його у високому середовищі транзакцій, і тому це не є типовим варіантом для запиту.


3
Єдиний раз, коли це потрібно, - це у високому середовищі транзакцій. Якщо ваші таблиці в основному простоюють, ви нічого не отримаєте.
Джонатан Аллен

7

Я використовую підказку (nolock), особливо в базах даних SQLServer 2000 з високою активністю. Я не впевнений, що це потрібно в SQL Server 2005, однак. Нещодавно я додав цю підказку в SQL Server 2000 на вимогу клієнта DBA, оскільки він помічав багато записів записів SPID.

Все, що я можу сказати, - це те, що використання підказки НЕ нашкодило нам і, здається, змусило вирішити проблему блокування. DBA у цього конкретного клієнта в основному наполягав на тому, що ми використовуємо підказку.

До речі, бази даних, з якими я маю справу, є спільними для корпоративних систем медичних претензій, тому ми говоримо про мільйони записів і 20+ таблиць у багатьох об'єднаннях. Зазвичай я додаю підказку WITH (nolock) для кожної таблиці підключення (якщо це не похідна таблиця; в такому випадку ви не можете використовувати саме цей підказку)


1
SQL Server 2005 додав "версію версій", яка повинна значно зменшити потребу в блокуваннях. Нещодавно ми оновили і не навчаємо наших DBA припиняти їх використання.
Джонатан Аллен

5

Найпростіша відповідь - це просте запитання - чи потрібні вам ваші результати для повторення? Якщо так, то NOLOCKS не підходить ні за яких обставин

Якщо вам не потрібна повторюваність, блокування може бути корисним, особливо якщо у вас немає контролю над усіма процесами, підключеними до цільової бази даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.