Чому слід використовувати ЧИТАЙ НЕЗАКОМЕНДОВАНИЙ рівень ізоляції?


225

Простий англійською мовою, які недоліки та переваги використання

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

у запиті для .NET-додатків та додатків служб звітності?

Відповіді:


210

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

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

Ви можете ознайомитися зі статтею Вікіпедії наREAD UNCOMMITTED декількох прикладах та читати далі.


Можливо, вам також буде цікаво ознайомитись із статтею блогу Джеффа Етвуда про те, як він та його команда вирішили проблему з тупиком у перші дні Stacka Overflow. За словами Джеффа:

Але nolockнебезпечно? Чи можете ви прочитати недійсні дані з read uncommittedувімкнутим? Так, теоретично. Ви не знайдете дефіциту космонавтів архітектури баз даних, які починають скидати науку про кислотні кислоти на вас і всіх, але не тягнуть будинок пожежної сигналізації, коли ви скажете їм, що хочете спробувати nolock. Це правда: теорія страшна. Але ось що я думаю: "У теорії немає різниці між теорією та практикою. На практиці існує".

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

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

Однією з альтернатив READ UNCOMMITTEDрівня, який ви можете розглянути, є READ COMMITTED SNAPSHOT. Знов цитую Джеффа:

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


13
Здається, автор натякає на те, що читання без відключення / без блокування не поверне те, що було зроблено востаннє. Наскільки я розумію, читання не передано, поверне будь-яке значення, яке було встановлено останнім часом, навіть якщо не було здійснено транзакцій. Якщо так, то результат не отримає дані "через кілька секунд застарілих". Було б (або принаймні, якщо транзакція, яка записує прочитані вами дані, повертається назад), отримуватиме дані, які не існують або ніколи не здійснювалися. Я помиляюся?
xr280xr

4
Чудова відповідь. До речі, Oracle має "знімок" за замовчуванням, оскільки я це знаю, ймовірно, десятиліттями до того, як сервер Sql представив його. Я був дуже розчарований, коли почав працювати з SQL Server, і виявив, що всі проблеми паралельності вирішуються за допомогою "примітивних" механізмів блокування. Ніколи не бачив "Читання не передано" в Oracle. І практикуючі такі ж щасливі, як і космонавти.
Штефан Штейнеггер

13
READ UNCOMMITTEDтакож може змусити вас читати рядки двічі або пропускати цілі рядки . Якщо розбиття сторінки відбувається під час читання, ви можете пропустити цілі фрагменти даних. WITH(NOLOCK)слід використовувати лише в тому випадку, якщо точність результатів не важлива
Ian Boyd

8
@DanielNolan, Рекомендувати цю статтю небезпечно, тому що Джефф не знав, що він робить . Непрограмоване читання має сенс лише для того, щоб читання даних ніколи не було змінено. Намагаючись використовувати це для читання таблиць, які були б написані, означає, що ви на практиці прочитаєте щось, що повернеться назад. Справа не лише в тому, що ви читаєте дані віком від декількох секунд, але ви .................................. ................... ‌ ‌ ........................... ....
Pacerier

5
................................... є читання даних, які ніколи навіть не здійснюються. Оце саме визначення зіпсованих читань. І якщо ви збираєтеся писати за результатами тих непрочитаних читань, ви на практиці будете записувати пошкоджені дані. Також у статті зазначено, що "MySQL, який виріс у веб-додатках, набагато менш песимістичний, ніж SQL Server". Неправда, сервер Sql працює за замовчуванням на рівні читання, в той час як MySQL працює на повторному читанні за замовчуванням, на відстані п'яти рівнів від нечитаного читання.
Pacerier

36

Це може бути корисно, щоб побачити хід довгих запитів вставки, зробити будь-які приблизні оцінки (наприклад, COUNT(*)грубі SUM(*)) тощо.

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


36

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

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

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

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


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

22

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

Якщо ви дбаєте про точність, не використовуйте це.

Більше інформації на MSDN :

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


Як це вплине на швидкість запиту?
Кіп Реал

11
@Kip - selectзаяви не доведеться чекати, щоб отримати спільні блокування на ресурсах, які виключно заблоковані іншими транзакціями.
Jarrod Dixon

15

Коли це нормально використовувати READ UNCOMMITTED?

Практичне правило

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

Ризиково : майже все інше.

Хороша новина полягає в тому, що більшість звітів лише для читання належать до цієї категорії « Добре ».

Детальніше ...

Гаразд, щоб використовувати його:

  • Майже всі сукупні звіти, що стоять перед користувачем, для поточних, нестатичних даних, наприклад, рік продажів. Він ризикує похибкою (можливо, <0,1%), що набагато нижче, ніж інші фактори невизначеності, такі як помилка введення або просто випадковість того, коли саме дані записуються хвилину в хвилину.

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

Коли ризиковано

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

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

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

Коли навіть ОК сценарій не в порядку.

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

Гарний момент щодо звітів. Насправді перша ідея, яка мені прийшла в голову, була, якщо я повинен використовувати read uncommittedдля веб-додатків, коли користувач бачить якусь сітку інтерфейсу користувача, де точність даних не так важлива. Користувач просто хоче короткий огляд, які записи можуть бути там, а може бути і з деякими підказками, сортуванням та фільтруванням. Тільки коли користувач натискає кнопку «Редагувати», я намагаюся прочитати найновіший запис із більш суворим рівнем ізоляції. Чи не повинен такий підхід бути кращим з точки зору продуктивності?
JustAMartin

Так, я думаю, що це розумно. Пам'ятайте, що більш важливою проблемою є переконання, що дані не були змінені кимось іншим за час натискання кнопки редагування та моменту надсилання. Ви можете впоратися з цим, запустивши транзакцію, отримуючи такі дані select item from things with (UPDLOCK). Поставте туди швидкий тайм-аут, щоб, якщо він не зміг швидко придбати блокування, він повідомить користувачеві, що його редагують. Це захистить вас не лише від користувачів, але і від розробників. Єдина проблема в тому, що ви повинні почати думати про очікування часу та про те, як ви впораєтесь із цим інтерфейсом.
Адамантиш

6

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


4

Використовуйте READ_UNCOMMITTED в ситуації, коли джерело малоймовірно змінити.

  • Під час читання історичних даних. наприклад, деякі журнали розгортання, які сталися два дні тому.
  • При повторному читанні метаданих. наприклад, додаток на основі метаданих.

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


1
Я відчуваю, що стосується зворотного. По-перше, статичні дані слід добре читати без блоків. Якщо ж блок , то тепер ви виявили , що є важлива проблема висить угоду виправити. Також користувачі очікують, що це збігатиметься до останнього знаку після коми, що б вони не надрукували для річного звіту минулого року. Зазвичай вони не очікують того самого звіту, про який вони знають, що постійно змінюється. Це не стосується детальної, надзвичайно чутливої ​​до часу фінансової звітності, але якщо 1 помилка введення в 1000 допустима, то так і є READ UNCOMMITTED.
Адамантиш

TLDR: Якщо дані не зміняться, вам не потрібно ПРОЧИТАТИ НЕЗАПАСНО, тому що блоків все одно немає. Якщо ви помиляєтесь, і все-таки зміниться, то це добре, що ви заблокували користувачів отримувати брудніші дані, ніж очікувалося.
Адамантиш

Так, я схильний погоджуватися з @Adamantish тут - ви можете отримати перевагу від READ UNCOMMITTEDбільшості ситуацій, коли ваші дані активно використовуються, і ви хочете зменшити навантаження на сервер, щоб уникнути можливих тупиків і відкатів транзакцій лише тому, що деякі користувачі, коли недбало зловживають " Оновити "на веб-сторінці із мережею даних. Користувачі, які переглядають купу записів одночасно, зазвичай не надто хвилюються, чи дані трохи застаріли або частково оновлені. Тільки тоді, коли користувач збирається редагувати запис, ви, можливо, захочете надати йому / їй найточніші дані.
JustAMartin

2

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

Також цікаво відзначити, що не відбувається. ЧИТАЙТЕ НЕЗАБАВЛЕНО не ігнорує лише інші блоки таблиці. Це також не викликає жодних замків.

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

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

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

Кращим способом може бути використання рівня СНАПШОТІВ ІЗОЛЯЦІЇ, але для ваших програм можуть знадобитися деякі коригування. Одним із прикладів цього є те, якщо ваша програма робить ексклюзивний замок на ряду, щоб запобігти її читанню та переходу в режим редагування в інтерфейсі користувача. СНАПШОТ ІЗОЛЯЦІЙНИЙ РІВЕНЬ також поставляється зі значним покаранням продуктивності (особливо на диску). Але ви можете подолати це, кинувши обладнання на проблему. :)

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


0

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


-7

Я завжди використовую "ЧИТАТИ НЕЗАКОМНО" зараз. Це швидко з найменшими проблемами. Під час використання інших ізоляцій ви майже завжди будете стикатися з деякими проблемами блокування.

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

Ви можете помилитися з ЧИТАЙТЕ НЕЗАМЕЖЕНО, але якщо чесно, дуже просто переконайтеся, що ваші вставки є повним підтвердженням. Вставки / оновлення, які використовують результати вибору, - це лише те, на що потрібно стежити. (Використовуйте тут ПРОЧИТАНО ЗАВАНТАЖЕНО або переконайтесь, що брудні читання не спричинить проблеми)

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


6
Це дуже неточно і лише торкається поверхні проблем, які можуть виникнути з блокуванням. Сторінки можуть розбиватися, приєднання може провалюватися, ви можете читати неіснуючі дані або дублювати дані. Немає можливості зробити його використання безглуздим: ви не можете довіряти точності нічого в рамках цього рівня ізоляції. ЧИТАЙТЕ ЗАВАНТАЖЕНИЙ СНАПШОТ - це менш небезпечна "фальшива панацея"
Марк Совул

@MarkSowul Схилення до цієї відповіді мені здається несправедливим. @Clive зрозуміло, що він перейде на Committedвставки та оновлення. Щодо інших проблем, він також продемонстрував обізнаність щодо розбиття сторінок, згадуючи використання ключа Авто-збільшення. Я погоджуюсь з ним, що майже вся реалізована репортаж, яку має читати просто людина, може допустити незначні розбіжності в остаточному десятковому знаку. Я погоджуюся, що це інша історія для детальних списків або даних, призначених для машинного зчитування та перетворення, як і Клайв.
Адамантиш

1
Цей коментар також демонструє відсутність повного розуміння можливих проблем, які виникають із блокуванням. "Незначні розбіжності в остаточному знаку після коми" навряд чи охоплюють це. Навіть торкатися "просто використовувати прочитане, зроблене для вставок / оновлень" є помилковим як загальна порада (що робити, якщо "вставити запис, якщо його не існує"?). У будь-якому випадку категорично неправильно "[читати не передається] швидко з найменшими питаннями".
Марк Совул

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