2.1 Read uncommitted

Під «рівнем ізоляції транзакцій» розуміється ступінь забезпечуваної внутрішніми механізмами СУБД (тобто не потребує спеціального програмування) захисту від усіх або деяких вищезгаданих видів неузгодженості даних, що виникають при паралельному виконанні транзакцій. Стандарт SQL-92 визначає шкалу із чотирьох рівнів ізоляції:

  • Read uncommitted
  • Read committed
  • Repeatable read
  • Serializable

Перший є найслабшим, останній — найсильнішим, кожен наступний включає у собі попередні.

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

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

2.2 Read committed

Більшість промислових СУБД, зокрема Microsoft SQL Server, PostgreSQL і Oracle, за замовчуванням використовують саме цей рівень. На цьому рівні забезпечується захист від чорнового, «брудного» читання, проте, в процесі роботи однієї транзакції, інша може бути успішно завершена і зроблені нею зміни зафіксовані. У результаті перша транзакція працюватиме з іншим набором даних.

Реалізація завершеного читання може ґрунтуватись на одному з двох підходів: блокування чи версійності.

Блокування даних, що читаються і змінюються.

Полягає в тому, що пишуча транзакція блокує змінювані дані для транзакцій, що працюють на рівні read committed або вищому, до свого завершення, перешкоджаючи, таким чином, «брудному» читанню, а дані, що блокуються читаючою транзакцією, звільняються відразу після завершення операції SELECT( таким чином, ситуація «читання, що не повторюється» може виникати на даному рівні ізоляції).

Збереження декількох версій рядків, що змінюються паралельно.

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

Крім того, при паралельній зміні даних декількома транзакціями може виникнути ситуація, коли кілька паралельних транзакцій зроблять неузгоджені зміни тих самих даних (оскільки блокування відсутні, ніщо не завадить це зробити). Тоді та транзакція, яка зафіксується першою, збереже свої зміни до основної БД, а решта паралельних транзакцій виявиться неможливо зафіксувати (оскільки це призведе до втрати оновлення першої транзакції). Єдине, що може в такій ситуації СУБД — це відкотити решту транзакцій та видати повідомлення про помилку «Запис уже змінено».

Конкретний спосіб реалізації вибирається розробниками СУБД, а деяких випадках може налаштовуватися. Так, за умовчанням MS SQL використовує блокування, але (у версії 2005 і вище) при установці параметра READ_COMMITTED_SNAPSHOTбази даних переходить на стратегію версійності, Oracle працює тільки за версійною схемою. У Informix можна запобігти конфліктам між транзакціями, що читають і пишуть, встановивши параметр конфігурації USELASTCOMMITTED(починаючи з версії 11.1), при цьому читаюча транзакція отримуватиме останні підтверджені дані.

2.3 Repeatable read

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

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

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

2.4 Serializable

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

2.5 Підтримка ізоляції транзакцій у реальних СУБД

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

Так, Oracle у принципі не підтримує нульовий рівень, тому що його реалізація транзакцій виключає «брудні читання», і формально не дозволяє встановлювати рівень Repeatable read, тобто підтримує лише ( Read committedза умовчанням) та Serializable. При цьому на рівні окремих команд він фактично гарантує повторюваність читання (якщо команда SELECTв першій транзакції вибирає з бази набір рядків, і в цей час паралельна друга транзакція змінює якісь з цих рядків, то результуючий набір, отриманий першою транзакцією, міститиме незмінені рядки, начебто другої транзакції не було). Також Oracle підтримує так звані READ-ONLYтранзакції, які відповідають Serializable, але не можуть самі змінювати дані.

А Microsoft SQL Server підтримує всі чотири стандартні рівні ізоляції транзакцій, а додатково — рівень SNAPSHOT, на якому транзакція бачить стан даних, який було зафіксовано до її запуску, а також зміни, внесені нею самою, тобто поводиться так, ніби отримала під час запуску моментальний знімок даних БД і з ним. Відмінність від Serialized полягає в тому, що не використовуються блокування, але в результаті фіксація змін може виявитися неможливою, якщо паралельна транзакція змінила ті ж дані раніше; у цьому випадку друга транзакція при спробі виконати COMMITвикличе повідомлення про помилку і буде скасована.