Різниця між "прочитаним зафіксованим" та "повторним читанням"


245

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


3
Вам слід розширити питання і додати теги для того, на який "рівень ізоляції" ви посилаєтесь (Java тощо). "рівень ізоляції" є дещо неоднозначним терміном, і ви, очевидно, просите відповіді для конкретного середовища.
jesup

Відповіді:


564

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

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

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

Скажімо, у вас є таблиця T зі стовпцем C з одним рядком у ній, скажімо, вона має значення "1". І вважаємо, що у вас є таке просте завдання, як наступне:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

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

  • у розділі ЧИТАТИ ЗВ'ЯЗАНО, другий SELECT може повернути будь-які дані. Одночасна транзакція може оновлювати запис, видаляти його, вставляти нові записи. Другий вибір завжди побачить нові дані.
  • у розділі REPEATABLE READ другий SELECT гарантовано відображатиме принаймні рядки, повернуті з першого SELECT в незмінному вигляді . Нові рядки можуть бути додані одночасно транзакцією за одну хвилину, але існуючі рядки не можна видалити і не змінити.
  • у розділі SERIALIZABLE читається, що другий вибір гарантовано бачить точно такі ж рядки, як і перший. Жоден рядок не може змінюватися, ні видалятися, ні нові рядки не можуть бути вставлені одночасно транзакцією.

Якщо дотримуватися вищевикладеної логіки, ви можете швидко зрозуміти, що СЕРІАЛІЗАЦІЙНІ транзакції, хоча вони можуть полегшити вам життя, завжди повністю блокують кожну можливу одночасну операцію, оскільки вони вимагають, щоб ніхто не міняв, не видаляв і не вставляв жодного рядка. Рівень ізоляції транзакцій за замовчуванням в області .Net System.Transactionsє серіалізаційним, і це, як правило, пояснює аномальну ефективність, що призводить до цього.

І нарешті, є також рівень ізоляції SNAPSHOT. Рівень ізоляції SNAPSHOT дає ті самі гарантії, що і серіалізаційні, але не вимагаючи, щоб жодна паралельна транзакція не могла змінювати дані. Натомість, він змушує кожного читача бачити власну версію світу (це власний "знімок"). Це робить програмування дуже легким, а також дуже масштабованим, оскільки не блокує одночасне оновлення. Однак ця вигода пов'язана з ціною: додаткове споживання ресурсів сервера.

Додаткові читання:


24
Я думаю, що є помилка вище для ПОВТОРЕННОГО ЧИТАННЯ: Ви кажете, що існуючі рядки не можна видалити і не змінити, але я думаю, що їх можна видалити або змінити, оскільки повторне читання просто зчитує "знімок", а не фактичні дані. З docs dev.mysql.com/doc/refman/5.0/en/… : "Усі послідовні зчитування в рамках однієї транзакції зчитують знімок, встановлений першим читанням."
Дерек Ліц

2
@Derek Litz Я правий у тому, що ви говорите: дані МОЖУТЬ / МОЖЕ бути змінені від третьої сторони, поки відбувається транзакція, але прочитані все одно побачать "старі" вихідні дані, як ніби зміни не відбулися місце (знімок).
Програміст

5
@Cornstalks. Так, Phantom зчитування може відбуватися з делетів (або вставок). Так, фантомні читання можуть відбуватися у повторюваній ізоляції читання (лише із вставок). Ні, зчитування з видалених Phantom не може відбуватися в повторюваній ізоляції читання. Перевірте це. Те, що я кажу, не суперечить цитованій вами документації.
AndyBrown,

4
@Cornstalks NP. Я згадував це взагалі, тому що я не був на 100% впевнений у собі і довелося глибоко пірнати, щоб бути впевненим, хто прав! І я не хотів, щоб майбутніх читачів вводили в оману. Залишаючи коментарі, мабуть, найкраще тримати так, як пропонується. Я впевнений, що хтось інший, хто зацікавився цим рівнем тонких деталей, буде досить конкретним, щоб прочитати всі коментарі !!
AndyBrown

12
Дякуємо, що не видалили ваші коментарі. Обговорення допомагає з'єднати більше крапок.
Джош

68

Повторне читання

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

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Читати прихильно

У контексті транзакції ви завжди отримуватимете останнє здійснене значення. Якщо ви отримаєте значення у session1, оновите його у session2, а потім отримаєте його у session1again, ви отримаєте значення, змінене у session2. Зчитується останній скоєний рядок.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Має сенс?


Я спробував повторне читання в SQL Server 2008 з "встановити рівень повторного читання рівня ізоляції". Створено два вікна запиту sql. Але не вийшло. Чому?
Aditya Bokade

1
Чому другий сеанс1 все ще зачитав Аарона? Чи не завершено та не здійснено транзакцію session2? Я знаю це старе, але, можливо, хтось може пролити трохи світла.
Сонні Чайлдс

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

4
У випадку повторного читання, коли сеанс 1 читає рядок, він ставить загальний замок, який не дозволить жодному Ексклюзивному блокуванню (до 2 сеансу) оновлення, отже, дані не можуть бути оновлені.
Тахер

Я думаю, що SQL-сервер і MySQL поводяться по-різному, коли мова заходить про оновлення спільних рядків між двома транзакціями
user2488286

23

Просто відповідь відповідно до мого читання та розуміння цієї теми та відповіді @ remus-rusanu ґрунтується на такому простому сценарії:

Існує два процеси A і B. Процес B читає таблицю X Процес A пише в таблицю X Процес B знову читає таблицю X.

  • ReadUncommitted : Процес B може читати невідомі дані з процесу A, і він може бачити різні рядки на основі написання B. Блокування взагалі немає
  • ReadCommitted : Процес B може читати ТОЛЬКО зафіксовані дані з процесу A, і він може бачити різні рядки на основі ЗАВАНТАЖЕНОГО запису лише B. ми могли б назвати це простим блокуванням?
  • RepeatableRead : Процес B прочитає ті самі дані (рядки), що і процес Process A. Але процес A може змінити інші рядки. Блок рівня рядків
  • Серійний доступ : Процес B буде читати ті самі рядки, що і раніше, а Процес A не може читати чи писати у таблиці. Блок рівня таблиці
  • Знімок : у кожного процесу є своя копія, і вони над цим працюють. У кожного є свій погляд

15

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

ЧИТАТИ ЗВ'ЯЗАНО (за замовчуванням)

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

ПОВТОРЕННЕ ЧИТАТИ

Спільні блокування беруться у SELECT та видаються лише після завершення транзакції . Таким чином система може гарантувати, що прочитані вами значення не зміняться під час транзакції (оскільки вони залишаються заблокованими до завершення транзакції).


13

Намагаючись пояснити цей сумнів простими схемами.

Читається Виконано: Тут на цьому рівні ізоляції транзакція T1 буде читати оновлене значення X, здійснене транзакцією T2.

Читати прихильно

Повторне читання: На цьому рівні ізоляції транзакція T1 не враховує зміни, здійснені транзакцією T2.

введіть тут опис зображення


1

Я думаю, що ця картина також може бути корисною, вона допомагає мені як орієнтир, коли я хочу швидко запам'ятати відмінності між рівнями ізоляції (завдяки kudvenkat на youtube)

введіть тут опис зображення


0

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


-1

Моє спостереження за початково прийнятим рішенням.

Під RR (mysql за замовчуванням) - якщо tx відкрито, і SELECT було запущено, інший tx НЕ може видалити будь-який рядок, що належить попередньому набору результатів READ, доки не буде скоєно попереднє tx (насправді видалення заяви у новому tx просто зависне) проте наступний tx може видалити всі рядки з таблиці без проблем. Btw, наступне ЧИТАННЯ в попередньому tx все ще буде бачити старі дані, поки вони не будуть скоєні.


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