Рівні ізоляції транзакцій із прикладами на PostgreSQL

Вступ

У стандарті SQL описується чотири рівні ізоляції транзакцій - Read uncommited (Читання незафіксованих даних), Read committed (Читання зафіксованих даних), Repeatable read (Повторюване читання) та Serializable (Серіалізовані). У цій статті буде розглянуто життєвий цикл чотирьох паралельно виконуваних транзакцій з рівнями ізоляціїRead committed таSerializable.

Для рівня ізоляції Read committed допустимі такі особливі умови для читання даних:

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

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

Що ж до Serializable, то даний рівень ізоляції найсуворіший, і не має феноменів читання даних.

ACID або 4 властивості транзакцій

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

Atomicity (атомарність) - виявляється у тому, що транзакція має бути виконана в цілому або не виконана зовсім.

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

Isolation (ізольованість) - локалізація користувальницьких процесів означає, що конкуруючі за доступ до БД транзакції фізично обробляються послідовно, ізольовано один від одного, але длякористувачів це виглядає, начебто вони виконуються паралельно.

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

Рівень ізоляції Read Committed

За промовчанням у PostgreSQL рівень ізоляції Read Committed. Такий рівень ізоляції завжди дозволяє бачити зміни внесені успішно завершеними транзакціями в паралельно відкритих транзакціях, що залишилися. У транзакції, що працює на цьому рівні, запит SELECT (без пропозиції FOR UPDATE/SHARE) бачить лише дані, які були зафіксовані до початку запиту; він ніколи не побачить незафіксованих даних чи змін, внесених у процесі виконання запиту паралельними транзакціями. По суті, запит SELECT бачить знімок бази даних у момент початку виконання запиту. Однак SELECT бачить результати змін, внесених раніше в цій транзакції, навіть якщо вони ще не зафіксовані. Також зауважте, що два послідовні оператори SELECT можуть бачити різні дані навіть у рамках однієї транзакції, якщо якісь інші транзакції зафіксують зміни після виконання першого SELECT.

Суть рівня ізоляції Read Committed показано на діаграмі 1.

Примітка: У таблиці вже знаходиться запис із першою версією даних (v1). Прошу приймати команди SELECT v1; — як команду, яка повертає дані версії v1, а UPDATE v1 to v2; як команду оновлення даних з першої версії до другої.

транзакцій

ізоляції

рівні

ізоляції

рівні

транзакцій

прикладами

рівні

рівні

прикладами

рівні

ізоляції

рівні

транзакцій

Примітка. На діаграмі не показано дію запиту INSERT. В рамках цьогорівня ізоляції, рядки додані, наприклад у кроці 3, Першої транзакції, були б ВИДНІ решті транзакцій після завершення Першої транзакції.

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

Рівень ізоляції Serializable

Ізоляція рівня Serializable забезпечує безперешкодний доступ до бази даних транзакцій із SELECT запитами. Але для транзакцій із запитами UPDATE та DELETE, рівень ізоляції Serializable не допускає модифікації одного і того ж рядка в рамках різних транзакцій. При ізоляції такого рівня всі транзакції обробляються так, ніби всі вони запущені послідовно (одна за одною). Якщо дві одночасні транзакції спробують оновити один і той же рядок, то це буде неможливо. У такому випадку PostgreSQL змусить транзакцію, другу, та й усі наступні, що намагалися змінити рядок до скасування (відкату - ROLLBACK).

Суть рівня ізоляції Serializable показана на діаграмі 2.

ізоляції

прикладами

рівні

транзакцій

прикладами

рівні

транзакцій

ізоляції

прикладами

ізоляції

транзакцій

транзакцій

транзакцій

ізоляції

Примітка. На діаграмі не показано дію запиту INSERT. В рамках цього рівня ізоляції, рядки додані, наприклад, у кроці 3, у Першій транзакції, були б НЕ ДОСТУПНІ Другій, Третьій та Четвертій транзакціям після завершення Першої транзакції. Також на діаграмі не показаний результат ROLLBACK (Кроки 8 та 11). Якби Друга і Третя транзакції робили якісь абозміни над не заблокованими даними, всі ці зміни були б зафіксовані, оскільки транзакції завершуються невдало (суть властивості — Atomicity).

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

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

Аномалія серіалізації (Втрачене оновлення)

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

Документація на сайті PostgreSQL PRO пише, що Read Committed допускає "Serialization Anomaly". Вітчизняна Wikipedia, не наполягаючи на те, що таблиця відноситься саме до PostgreSQL, пише, що Read Commited запобігає аномалії серіалізації. Англійська Вікіпедія про такий феномен читання даних замовчує. Але німецька Вікіпедія наводить у своїй версії таблиці феномен «Lost Updates», вказуючи на те, що Read Committed може бути не схильний до втрати оновлень з додатковим захистом через курсор (Cursor Stability). Українська Вікіпедія підтримує українську версію статті, іспанська Вікіпедія підтримує англійську версію статті. Англомовна документація PostgreSQL не відрізняється від документації з сайту PostgreSQL PRO.

Cursor Stability розширює блокувальну поведінку рівня READ COMMITED дляSQL-курсорів, додаючи нову операцію читання (Fetch) курсором rc (означає read cursor, тобто читання курсором) і вимагаючи, щоб блокування встановлювалася на поточному елементі курсора. Блокування утримується доти, доки курсор не буде переміщений (доки не зміниться його поточний елемент) або закритий, можливо, операцією фіксації. Природно, транзакція, яка читає курсором, може змінити поточний рядок (wc – запис курсору), й у разі блокування по запису цього рядка буде зберігатися до того часу, поки транзакція не зафіксується, навіть після пересування курсора з наступною вибіркою наступного рядка.

рівні

Висновок

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

Література

Тільки зареєстровані користувачі можуть брати участь в опитуванні. Заходьте будь ласка.