Рівні ізольованості транзакцій

Матеріал з Вікіпедії — вільної енциклопедії.
Версія від 16:30, 12 травня 2020, створена BunykBot (обговорення | внесок) (заміна застарілого тегу source)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

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

Проблеми паралельного доступу з використанням транзакцій

[ред. | ред. код]

При паралельному виконанні транзакцій можливі такі проблеми:

  • втрачене оновлення (англ. lost update) — при одночасній зміні одного блоку даних різними транзакціями, одна із змін втрачається;
  • «брудне» читання (англ. dirty read) — читання даних, які додані чи змінені транзакцією, яка потім не підтвердиться (відкотиться);
  • неповторюване читання (англ. non-repeatable read) — при повторному читанні в рамках однієї транзакції, раніше прочитані дані з’являються зміненими;
  • фантомне читання (англ. phantom reads) — одна транзакція в ході свого виконання декілька разів вибирає множину рядків за одними і тими ж критеріями. Інша транзакція в інтервалах між цими вибірками додає чи видаляє рядки чи змінює стовпці деяких рядків, що використовується в критеріях вибірки першої транзакції, і успішно закінчується. В результаті отримаємо, що одні і ті ж вибірки в першій транзакції дають різні множини рядків.

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

Втрачене оновлення

[ред. | ред. код]

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

Припустимо, є дві транзакції, що виконуються одночасно:

Транзакція 1 Транзакція 2
UPDATE tbl1 SET f2=f2+20 WHERE f1=1;
UPDATE tbl1 SET f2=f2+25 WHERE f1=1;

В обох транзакціях змінюється значення поля f2, при цьому одна з змін втрачається. Так що, f2 буде збільшене не на 45, а тільки на 20 або 25.

Це трапляється тому, що:

  1. Перша транзакція прочитала поточний стан поля.
  2. Друга транзакція зробила свої зміни, базуючись на своїх, збережених в пам’яті, даних.
  3. Перша оновлює поле, використовуючи свої "старі" дані.

«Брудне» читання

[ред. | ред. код]

Читання даних, які додані чи змінені транзакцією, яка згодом не підтвердиться (відкотиться).

Припустимо, є дві транзакції, відкриті в різних з’єднаннях з базою, в яких виконані такі SQL-оператори:

Транзакція 1 Транзакція 2
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
ROLLBACK;

В транзакції 1 змінюється значення поля f2, а потім в транзакції 2 вибирається значення цього поля. Після цього трапляється відкат транзакції 1. В результаті значення, отримане другою транзакцією, буде відрізнятись від значення, що зберігається в базі даних.

Неповторюване читання

[ред. | ред. код]

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

Припустимо, є дві транзакції, відкриті в різних сесіях, в яких виконані такі SQL оператори:

Транзакція 1 Транзакція 2
SELECT f2 FROM tbl1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
COMMIT;
SELECT f2 FROM tbl1 WHERE f1=1;

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

Фантомне читання

[ред. | ред. код]

Ситуація, коли при повторному читанні в рамках однієї транзакції одна і та ж вибірка дає різні множини рядків.

Припустимо, є дві транзакції, відкриті в різних сесіях, в яких виконані такі SQL оператори:

Транзакція 1 Транзакція 2
SELECT SUM(f2) FROM tbl1;
INSERT INTO tbl1 (f1,f2) VALUES (15,20);
COMMIT;
SELECT SUM(f2) FROM tbl1;

В транзакції 2 виконується SQL оператор, який використовує всі значення поля f2. Потім, в транзакції 1, виконується вставка нового рядка, яка призводить до того, що повторне виконання SQL оператора в транзакції 2, видасть інший результат. Така ситуація називається фантомним читанням. Від неповторюваного читання воно відрізняється тим, що результат повторного звернення до даних змінився не через змінення/видалення самих цих даних, а через появу нових (фантомних) даних.

Рівні ізоляції

[ред. | ред. код]

Стандарт SQL-92 визначає рівні ізоляції, установка яких запобігає деяким конфліктним ситуаціям. Введені наступні чотири рівні ізоляції:

Serializable (впорядкованість)

[ред. | ред. код]

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

Repeatable read (повторюваність читання)

[ред. | ред. код]

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

Read committed (читання фіксованих даних)

[ред. | ред. код]

Прийнятий за замовчуванням рівень для Microsoft SQL Server. Закінчене читання, при якому відсутнє «брудне» читання (тобто, читання одним користувачем даних, що не були зафіксовані в БД командою COMMIT). Проте, в процесі роботи однієї транзакції інша може бути успішно закінчена, і зроблені нею зміни зафіксовані. В підсумку, перша транзакція буде працювати з іншим набором даних. Це проблема неповторюваного читання.

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

В Informix можна запобігти конфліктам між транзакціями, що читають та пишуть, встановивши параметр конфігурації USELASTCOMMITTED (починаючи з версії 11.1), при цьому транзакція, що читає, буде отримувати останні підтверджені дані[1]

Read uncommitted (читання незафіксованих даних)

[ред. | ред. код]

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

Поведінка при різних рівнях ізольованості

[ред. | ред. код]

«+» — запобігає, «-» — не запобігає.

Рівень ізоляції Фантомне читання Неповторюване читання «Брудне» читання Втрачене оновлення[3]
SERIALIZABLE + + + +
REPEATABLE READ - + + +
READ COMMITTED - - + +
READ UNCOMMITTED - - - +

Примітки

[ред. | ред. код]

Посилання

[ред. | ред. код]