Чи погана практика NOLOCK (підказка сервера Sql)?


125

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

Отже, з цією масовою відмовою, чи погано використовувати підказку NOLOCK у деяких заявах Sql? Кілька років тому колега адміністратора Sql запропонував мені використовувати NOLOCK, якщо я задоволений "брудним читанням", яке дасть мені трохи більше продуктивності в моїй системі, оскільки кожне читання не блокує блокування стіл / рядок / що завгодно.

Мені також сказали, що це прекрасне рішення, якщо я відчуваю мертві замки. Отже, я почав дотримуватися цієї думки протягом декількох років, поки гуру Sql не допоміг мені якийсь випадковий код і помітив усі НОЛОКИ в моєму кодексі sql. Мене ввічливо лаяли, і він намагався пояснити мені це (чому це не дуже добре), і я сорта заблукала. Я відчув, що суть його пояснення полягала в тому, що «це вирішення більш серйозної проблеми», особливо якщо ви відчуваєте тупик. Як таке, виправте корінь проблеми '.

Нещодавно я про це погуглився і натрапив на цю посаду .

Отже, може ласка, будь ласка, просвітить мене якийсь sql db guru sensei?


Я не розумію цього, Сем, ти кажеш, використовуй знімок Snapshot, якщо це веб-сайт, який читає важко. Але тоді ти кажеш, ТАК це зробив, і це погано? чи просто їх використання NOLOCK?
Pure.Krome

Відповіді:


67

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

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

Я пропоную прочитати, коли ізоляція знімків допомагає і коли болить - MSDN рекомендує використовувати ПРОЧИТАНО ЗАВАНТАЖЕНИЙ СНАПШОТ, а не SNAPSHOT за більшості обставин.


1
Рекс, не соромтесь додати примітку про ізоляцію знімків.
Сам Шафран

2
Так, Сем говорить про ізоляцію знімка, і ви пропонуєте прочитати знімок. я так заплутався: P (а я ще ще вникаю в статті, теж!)
Pure.Krome

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

NOLOCK == Мені все одно, якщо пропущені рядки пропущено, невмінні рядки включені, в рідкісних випадках той самий рядок повертається не один раз, а в дуже рідкісних випадках повертаються рядки, які не відповідають моєму запиту. (див. blogs.msdn.com/b/sqlcat/archive/2007/02/01/… , знайдений з іншого SO q'n на цю тему)
Andrew Hill

106

До роботи над переповненням стека я виступав проти NOLOCKпринципу, який ви потенційно можете виконати SELECTз NOLOCKі отримати результати з даними, які можуть бути застарілими або непослідовними. Важливим фактором є те, скільки записів може бути вставлено / оновлено одночасно. Інший процес може вибирати дані з тієї ж таблиці. Якщо цього трапляється багато, то велика ймовірність тупиків, якщо ви не використовуєте режим бази даних, наприклад READ COMMITED SNAPSHOT.

З тих пір я змінив свою точку зору на використання NOLOCKпісля того, як став свідком того, як це може підвищити SELECTпродуктивність, а також усунути тупикові місця на масово завантаженому SQL Server. Бувають випадки, коли вас може не хвилювати, що ваші дані не є стовідсотково відданими, і вам потрібні результати швидко, хоча вони можуть бути застарілими.

Задайте собі питання, думаючи про використання NOLOCK:

Чи включає мій запит таблицю з великою кількістю INSERT/ UPDATEкоманд і чи мені байдуже, чи можуть дані, повернуті з запиту, пропустили ці зміни в даний момент?

Якщо відповідь - ні, тоді використовуйте NOLOCKдля покращення продуктивності.


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


7
ІМО, це трохи спрощено. Тупики можна усунути, використовуючи покривні індекси, знімаючи тиск з індексу кластеру.
Мітч Пшеничний

8
Я не хочу зменшувати значення хорошого покриття індексів. Буває, що запити, що використовують NOLOCK, можуть додати додаткову продуктивність, окрім виграшів, реалізованих за допомогою індексів на таблицях з великою кількістю вставок / оновлень. Швидкість запиту на переповнення стека є першорядною навіть за рахунок недостовірних або відсутніх даних.
Джефф Дальгас

9
Мабуть, можна отримати повторювані рядки, використовуючи NOLOCK. Це означає, що я повинен спростувати вашу відповідь. Вибачте.
ЕрікЕ

1
@MitchWheat A SELECT, читаючи лише з індексу покриття, може спричинити тупик. SPID 1) почати SELECTз індексу покриття. SPID 2) Почніть UPDATEтаблицю. Потім оновлення переходить до оновлення індексу покриття. UPDATEдосягає діапазону індексу, заблокованого SELECTі блокується. SPID 1) все ще шукаючи індекс покриття, знаходить діапазон, заблокований UPDATEі блокується. РОЗВИТОК . Ніщо не може вирішити цей глухий кут (окрім вилучення помилки 1205 SQL Server та автоматичної повторної спроби чи використання NOLOCK)
Ian Boyd

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

20

Якщо ви не переймаєтесь брудними читаннями (тобто, в основному, ЧИТАТИ), то NOLOCKце добре.

Але майте на увазі, що більшість проблем із блокуванням пов’язані з відсутністю "правильних" індексів для вашої завантаженості запиту (якщо припустимо, що апаратне забезпечення вирішує завдання).

І пояснення гуру було правильним. Зазвичай це вирішення більш серйозної проблеми.

Редагувати : Я точно не пропоную використовувати NOLOCK. Я думаю, я мав би зробити це очевидно зрозумілим. (Я б коли-небудь використовував його лише в екстремальних обставинах, коли я проаналізував, що це нормально). Як приклад, деякий час назад я працював над деяким TSQL, який був посипаний NOLOCK, щоб спробувати усунути проблеми блокування. Я видалив їх усіх, застосував правильні індекси, і ВСІ з тупиків пішли.


3
Хм .. я досі не розумію. Так це добре, але це також погана форма .. це те, що ви говорите?
Pure.Krome

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

2
Добре, я не думаю, що його справедливий рексем був просто сприйнятий, я думаю, що ви не зверталися до довільних помилок, які просто виникають під час використання блокування. Недоречно раз на час на вашому веб-сайті з’являти порожню сторінку з помилками, це справді погана форма. Мені не подобається твердження, що "якщо ти не дбаєш про брудне, читає його штраф" ... це не добре, навіть якщо ти не дбаєш про брудні читання
Сем Шафран

Порожня сторінка, яку ви отримуєте, коли запит генерує виняток, для якого ви не застосували логіку спроби. Що відбувається на ваших сайтах, коли результати виконання запитів за винятком, чи є у вас всюди логіка повтору?
Сам Шафран

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

13

Сумніваєтесь, що це був "гуру", який мав будь-який досвід у великому трафіку ...

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

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

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

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

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

Використання підказки NOLOCK в EF4?


10

Жодна з відповідей не є помилковою, проте, можливо, трохи заплутаною.

  • Під час запиту поодиноких значень / рядків завжди погана практика використовувати NOLOCK - ви, ймовірно, ніколи не хочете відображати неправильну інформацію або, можливо, навіть вживати будь-яких дій щодо неправильних даних.
  • Відображаючи грубу статистичну інформацію, NOLOCK може бути дуже корисним. Візьміть ТА як приклад: Було б дурницею брати блокування, щоб прочитати точну кількість переглядів питання або точну кількість питань для тегу. Нікого не хвилює, якщо ви неправильно вказали 3360 питань із тегом "sql-сервер" зараз, а через відкат транзакцій 3359 запитань через секунду.

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

1
Ні це не так. Рядок може змінюватися з інших причин, наприклад, вставляючи інший рядок, розбиває сторінку. Правильна індексація, Прочитане Зроблений знімок та Ізольований знімок майже завжди є кращими ідеями.
Марк Совул

1
@tuseau, якщо ви "знаєте", що жоден інший процес не матиме доступу до рядка, акт зняття блокування нічого не заблокує, тому коштує вам (практично) нічого,
Andrew Hill

2

Як професійний розробник, я б сказав, що це залежить. Але я безумовно дотримуюся порад GATS та OMG Ponies. Знай, що ти робиш, знай, коли це допомагає і коли болить і

читайте підказки та інші погані ідеї

що може змусити вас зрозуміти сервер sql глибше. Я, як правило, дотримуюся правила, що підказки SQL - ЗЛИВ, але, на жаль, я їх використовую раз у раз, коли мені набридло змушувати SQL-сервер робити щось ... Але це рідкісні випадки.

лука


2

Коли підтримка додатків хотіла відповісти на рекламні запити від виробничого сервера за допомогою SSMS (на який не зверталися звітності), я попросив використовувати нолок. Таким чином "головний" бізнес не впливає.


2

Я погоджуюся з деякими коментарями щодо натяку на NOLOCK, а особливо з тими, що говорять "використовуй його, коли це доречно". Якщо програма написана погано і використовує сумісність невідповідним чином - це може спричинити ескалацію блокування. Сильно транзакційний стіл також постійно замикається через свою природу. Добре охоплення індексом не допоможе отримати дані, але встановлення ІЗОЛАЦІЙНОГО РІВНЯ НА ПРОЧИТАННЯ НЕЗАКОМОВАНО. Також я вважаю, що використання підказки NOLOCK є безпечним у багатьох випадках, коли характер змін передбачуваний. Наприклад - у виробництві, коли завдання з мандрівниками проходять різні процеси з великою кількістю вкладених вимірів, ви можете сміливо виконувати запит щодо готової роботи з підказкою NOLOCK, і таким чином уникнути зіткнення з іншими сеансами, які ставлять PROMOTED або EXCLUSIVE блокування на стіл / сторінку. Дані, до яких ви отримуєте доступ у цьому випадку, є статичними, але вони можуть міститись у дуже транзакційній таблиці із сотнями мільйонів записів та тисячами оновлень / вставок за хвилину. Ура


2

Я вважаю, що користуватися nolock практично ніколи не правильно.

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

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

NOLOCK - це сурогатний тег: "Мені все одно, чи ця відповідь містить дублікати рядків, рядки, які видаляються, або рядки, які ніколи не були вставлені для початку через відкат"

Помилки, які можливі в NOLOCK:

  • Рядки, які відповідають, взагалі не повертаються.
  • одні рядки повертаються кілька разів (включаючи кілька екземплярів одного і того ж первинного ключа)
  • Рядки, які не відповідають, повертаються.

Будь-яка дія, яка може призвести до розбиття сторінки під час запуску вибору noLock, може призвести до цього. Практично будь-яка дія (навіть видалення) може спричинити розкол сторінки.

Отже: якщо ви "знаєте", що рядок не буде змінено під час запуску, не використовуйте nolock, оскільки індекс дозволить ефективно шукати.

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

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


2

Кращі рішення, коли це можливо:

  • Тиражуйте свої дані (використовуючи реплікацію журналу) у базі даних звітів.
  • Використовуйте знімки SAN та змонтуйте послідовну версію БД
  • Використовуйте базу даних, яка має кращий рівень ізоляції транзакцій

Рівень ізоляції транзакцій SNAPSHOT був створений через те, що MS втрачала продажі Oracle. Для уникнення цієї проблеми Oracle використовує журнали скасування / повторення. Postgres використовує MVCC. У майбутньому Хекатон МС використовуватиме MVCC, але це вже багато років від готовності виробництва.


Там надрукована помилка. Я маю на увазі сказати "кращий фундаментальний механізм ізоляції транзакцій".
pwy

1
Рівень ізоляції транзакцій SNAPSHOT - це винахід MS. В основному він поміщає дані в темп-таблицю в TEMPDB. Ця БД поділяється між усіма БД у полі. Отже, ви захочете використовувати SSD для TEMPDB, коли це можливо. Це, мабуть, менше зусиль, ніж інші варіанти.
pwy

1

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

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

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

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

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


-2

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


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