Переваги НАРУШЕННЯ ІЗОЛАЦІЙНОГО ІЗОЛЯЦІЙНОГО РОЗВИТКУ ЧИТАТИ НЕЗАКОННО


12

Я використовую SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDв більшості своїх загальних SQL запитів, головним чином тому, що це було розроблено для мене під час вивчення мови.

З мого розуміння, цей рівень ізоляції діє так само, WITH (NO LOCK)як і я, коли я схильний використовувати SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

  • Чи є коли-небудь час, який я повинен використовувати WITH (NO LOCK)більше SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED?
  • Чи SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDперешкоджає іншим користувачам закриватися з-за таблиць, які я читаю?
  • Якщо SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDвикористовується для зупинки блокування, але я лише читаю дані, який сенс у її використанні? Чи генерувати блокування будуть лише інтенсивні запити системи? Чи варто використовувати його під час запуску запитів, які повернуться, скажімо, за 5-10 секунд?
  • Мені сказали не використовувати SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDпри читанні даних, які будуть використовуватися в оновленнях, імовірно, щоб уникнути оновлення брудних даних. Це було б єдиною причиною?
  • З типом бази даних, над якою я працюю, існує виробниче та тестувальне середовище. Ми дуже рідко запитуємо виробниче середовище, але коли мені потрібно, я зазвичай використовую SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDу своєму запиті. Я розумію, що з цим можливі брудні читання. Окрім того, щоб отримати назад дані, які, можливо, не будуть передані в базу даних (і тому викидають мої результати), які ще види "брудних читань" можуть бути можливими?

Вибачте за масові запитання.


2
Ви могли прочитати одні й ті самі дані двічі - це ще одне падіння. Використання RU або NO LOCK в якості стандарту - погана ідея.
Джеймс Андерсон

9
Я б не використовував READ UNCOMMITTEDвсюди точно так само, як я б не використовував WITH (NOLOCK)всюди (вони по суті одне й те саме) blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere
Марк Сінкінсон

1
Погляньте на моделі ізоляції SNAPSHOT. Вони дуже сильніші за RCU, а також не блокують і не викликають блокування. Вони звучать як хороша модель за замовчуванням для вас (замість дефолту до RCU!).
usr

Відповіді:


26

Страшно, що ти так це навчився (вибач!).

READ UNCOMMITTEDдавайте читатимемо кожен рядок, так. Навіть ті , хто в даний час використовується в INSERT, UPDATE, DELETEопераціях. Це дуже корисно, якщо вам потрібно швидко ознайомитися з деякими Даними або в критично важливих місіях, SELECTде блок буде дуже шкідливим.

Насправді ви ризикуєте своєю доброчесністю. Може статися, що ви читаєте рядок, який зараз використовується для видалення або зміни. Також може здатися, що ви читаєте неправильне значення. Це може бути справді нечасто, але це може статися. Що я маю на увазі під цим? Ну, придумайте дуже широкий ряд (у ньому багато стовпців з багатьма довгими nvarcharстовпцями). У цьому рядку відбувається оновлення та встановлює нові значення. У рідкісних випадках вам може трапитися, що ви читаєте лише половину рядка. Інша річ може статися, наприклад, якщо користувач змінить свої вхідні значення. Він змінює свою пошту + пароль. Пошта вже встановлена, але пароль - ні. Таким чином у вас є непослідовний стан.

Я б запропонував забути READ UNCOMMITTED. Просто використовуйте його там, де це дійсно потрібно.

Іншою альтернативою для вас може бути ввімкнути параметр READ_COMMITTED_SNAPSHOTбази даних - для цього ви можете використовувати READ COMMITTED SNAPSHOTзавдяки увімкненій версії рядків у своєму tempdb. Таким чином ви просто прочитали іншу (старішу) версію рядка. Це не блокує ваші запити. Але може статися, що ви читаєте і старе значення, але постійне старе значення.

Інша ідея може бути WITH(READPAST)замість WITH(NOLOCK). Ви прочитаєте старий стан таблиці (трохи як у SNAPSHOT ISOLATION), але замість цього пропустите всі заблоковані рядки.


@Ionic, дуже дякую за відгук! Я дуже ціную допомогу в цьому.
dmoney

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

1
SNAPSHOT ISOLATIONне потрібно включати, щоб увімкнути READ COMMITTED SNAPSHOT. READ COMMITTED SNAPSHOTПотрібно ввімкнути лише параметр бази даних, щоб версії рядків замість блокування для послідовності читання уникали необхідності брудного читання.
Дан Гузман

Так, я погрожував це @DanGuzman. Вибачте, відповідь була трохи незрозумілою в цьому пункті. Я це відредагував. :-)
Іонічний

Завдяки READPAST ви будете пропускати записи, які заблоковані, старих значень ви не отримаєте - тому єдине місце, за яким я зрозумів, що це може бути використане, - це обробка черг
James Z

2

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

  1. Під час написання та тестування пакетів SSIS SQL Server, дії цього пакету можуть бути перетворені в транзакцію. Якщо ви тестуєте пакет, запускаючи його поетапно у відладчику SSIS, можливо, ви захочете вивчити таблиці, поки на столі є блокування. Використання НАРУШЕННЯ ІЗОЛЯЦІЇ ТРАНЗАКЦІЙНОГО РОЗВИТКУ ПРОЧИТАЙТЕ НЕЗАКОМНОГО дозволяє використовувати SQL Server Manager Studio для вивчення таблиць під час налагодження пакету.

  2. У студії SQL Server Manager ви можете перевірити T-SQL-код, загорнувши його в транзакцію, щоб дати вам можливість повернути зміни. Наприклад, у тестовій базі даних, можливо, ви захочете відновити дані до початкового стану як частину вашого тесту. Якщо ви тестуєте код, оброблений транзакцією, і хочете перевірити заблоковані таблиці під час виконання транзакції, ви можете використати НАСТРОЙКИ ІЗОЛЯЦІЇ ІЗОЛЯЦІЇ ТРАНЗАЦІЇ, ЧИТАЙТЕ НЕЗАКОМНОГО, щоб вивчити значення в іншому вікні.

Я погоджуюсь, що це досить малозрозуміло використання для ПРОЧИТАННЯ НЕЗАПАСНО, але я вважаю їх корисними в тестовому середовищі.


1

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

Звичайно, READ UNCOMMITTED(брудні читання) можуть подати неправдиву інформацію в цих випадках, але ця інформація була правильною на 5 секунд раніше.

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

Тим часом, у типовій великій, зайнятій базі даних, яка має 100 (або більше) до 1 співвідношення читання до запису, ВСЕ єдиний запит (читання), який не використовує "Брудні читання", уповільнює роботу системи, оскільки її потрібно отримати та перевірити для замків І це робить набагато більш імовірним, що трансакції будуть провалюватися (як правило, через тупикові місця), що може спричинити більш серйозні проблеми з цілісністю бази даних.

Натомість використання брудних зчитувань робить систему МНОГО швидшою та надійнішою (частково через покращену продуктивність, що робить невідповідності менш ймовірними).

Звичайно, бувають випадки, коли їх не слід використовувати. Мені не подобається встановлення бази даних за замовчуванням для використання READ UNCOMMITTEDрівня ізоляції або навіть використання явного SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDтвердження на початку SQL-скриптів та SP-файлів - є занадто велика ймовірність, що брудне читання станеться, коли воно не повинно. Натомість, (NOLOCK)підказки є набагато кращим підходом, оскільки вони прямо вказують на те, що програміст задумався над тим, що вони роблять, і вирішили, що для цієї конкретної таблиці в цьому конкретному запиті Dirty Reads є безпечною.

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

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