1.1 Вступ
А тепер розпочнеться найцікавіше – теорія роботи транзакцій. Як зберегти працездатність системи, коли у вас змінюються ті самі дані в різних потоках? Чи хочеться виконати одну транзакцію до іншої? Відповіді на ці питання ми почнемо шукати з вивчення ізольованості транзакцій.
Рівень ізольованості транзакцій - умовне значення, що визначає, якою мірою в результаті виконання логічно паралельних транзакцій в СУБД допускається отримання неузгоджених даних. Шкала рівнів ізольованості транзакцій містить ряд значень, про ранжованих від нижчого до найвищого; більш високий рівень ізольованості відповідає кращій узгодженості даних, але його використання може знижувати кількість транзакцій, що фізично паралельно виконуються.
І навпаки, нижчий рівень ізольованості дозволяє виконувати більше паралельних транзакцій, але знижує точність даних. Таким чином, вибираючи використовуваний рівень ізольованості транзакцій, розробник інформаційної системи певною мірою забезпечує вибір між швидкістю роботи та забезпеченням гарантованої узгодженості даних, що отримуються з системи.
Проблеми паралельного доступу з використанням транзакцій
При паралельному виконанні транзакцій можливі такі:
- втрачене оновлення (англ. lost update) - при одночасному зміні одного блоку даних різними транзакціями втрачаються всі зміни, крім останнього;
- "брудне" читання (англ. dirty read) - читання даних, доданих або змінених транзакцією, яка згодом не підтвердиться (відкотиться);
- неповторне читання (англ. non-repeatable read) - при повторному читанні в рамках однієї транзакції раніше прочитані дані виявляються зміненими;
- фантомне читання (англ. phantom reads) - одна транзакція в ході свого виконання кілька разів вибирає безліч рядків за одними і тими ж критеріями. Інша транзакція в інтервалах між цими вибірками додає рядки або змінює стовпці деяких рядків, які використовуються за умов вибірки першої транзакції, та успішно закінчується. У результаті вийде, що одні й самі вибірки у першій транзакції дають різні безлічі рядків.
Розглянемо ситуації, у яких можливе виникнення цих проблем.
1.2 Втрачене оновлення
Ситуація, коли при одночасному зміні одного блоку даних різними транзакціями одна зі змін втрачається.
Припустимо, є дві транзакції, що виконуються одночасно:
Транзакція 1 | Транзакція 2 |
---|---|
UPDATE tbl1 SET f2=f2+20 WHERE f1=1; | UPDATE tbl1 SET f2=f2+25 WHERE f1=1; |
В обох транзакціях змінюється значення поля f2, після завершення значення поля має бути збільшено на 45. Насправді може виникнути наступна послідовність дій:
- Обидві транзакції одночасно читають стан поля. Точна фізична одночасність тут не є обов'язковою, достатньо, щоб друга по порядку операція читання виконалася до того, як інша транзакція запише свій результат.
- Обидві транзакції обчислюють нове значення поля, додаючи, відповідно, 20 і 25 раніше прочитаного значення.
- Транзакції намагаються записати результат обчислень у полі f2. Оскільки фізично одночасно два записи виконати неможливо, насправді одна з операцій запису буде виконана раніше, інша пізніше. При цьому друга операція запису перезапише результат першої.
В результаті значення поля f2 після завершення обох транзакцій може збільшитися не на 45, а на 20 або 25, тобто одна з транзакцій, що змінюють дані, «пропаде».
1.3 «Брудне» читання
Читання даних, доданих або змінених транзакцією, яка не підтвердиться (відкотиться).
Припустимо, є дві транзакції, відкриті різними додатками, в яких виконані такі SQL-оператори:
Транзакція 1 | Транзакція 2 |
---|---|
UPDATE tbl1 SET f2=f2+1 WHERE f1=1; | |
SELECT f2 FROM tbl1 WHERE f1=1; | |
ROLLBACK WORK; |
У транзакції 1 змінюється значення поля f2, а потім транзакції 2 вибирається значення цього поля. Після цього відбувається відкат транзакції 1. В результаті значення, отримане другою транзакцією, відрізнятиметься від значення, що зберігається в базі даних.
1.4 Неповторне читання
Ситуація, коли при повторному читанні в рамках однієї транзакції, раніше прочитані дані виявляються зміненими.
Припустимо, є дві транзакції, відкриті різними додатками, в яких виконані такі SQL-оператори:
Транзакція 1 | Транзакція 2 |
---|---|
SELECT f2 FROM tbl1 WHERE f1=1; | |
UPDATE tbl1 SET f2=f2+3 WHERE f1=1; | |
COMMIT; | |
SELECT f2 FROM tbl1 WHERE f1=1; |
У транзакції 2 вибирається значення поля f2, потім транзакції 1 змінюється значення поля f2. При повторній спробі вибору значення з поля f2 транзакції 2 буде отримано інший результат. Ця ситуація особливо неприйнятна, коли дані зчитуються з метою їхньої часткової зміни та зворотного запису до бази даних.
1.5 Читання «фантомів»
Ситуація, коли при повторному читанні в рамках однієї транзакції одна і та ж вибірка дає різні множини рядків.
Припустимо, є дві транзакції, відкриті різними додатками, в яких виконані такі 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 видасть інший результат. Така ситуація називається читанням фантома (фантомним читанням). Від читання, що не повторюється, воно відрізняється тим, що результат повторного звернення до даних змінився не через зміну/видалення самих цих даних, а через появу нових (фантомних) даних.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ