Мета розділу – вивчення особливостей використання різних рівнів ізольованості транзакцій, які гарантовано забезпечують цілісність реляційних даних при їх спільному корегуванні декількома користувачами.
Для локальних СКБД (Paradox, dbase і т. ін.) характерний підхід термінового відображення змін. Відмовитися від модифікації даних у цьому разі неможливо, оскільки зміни вже фізично внесені в БД. Але, вилучений запис можна ввести знову вручну. Або інший варіант: вилучені записи можна зберігати в деякому проміжному (тимчасовому) відношенні БД. Якщо виникла потреба відмовитися від вилучення записів, то їх можна перемістити з тимчасового сховища у те відношення, з якого вони були вилучені.
Відмову від кожного модифікування даних в одному або декількох відношеннях називають відкотом до останнього стану БД, у якому забезпечуються всі види цілісності даних – посилальна цілісність, цілісність сутностей та корпоративні обмеження цілісності. Таким чином, будь-яка модифікація інформації в БД має гарантувати їй перехід з одного цілісного стану в інший.
Класичним прикладом переходу БД є бухгалтерська проводка: деяка сума коштів S має бути списана з одного рахунку К та зарахована на іншій – D. Тільки успішне виконання цих двох операцій гарантує цілісність інформації в БД. Але цілісність буде порушена, якщо в результаті збою сума S буде списана з рахунку К, але не буде зарахована на рахунок D або, навпаки, зарахована на D, але не списана з К. Тому у разі помилки списання/зарахування суми результати попередньої операції зарахування/списання мають бути скасовані. Інакше кажучи, бухгалтерська проводка складається з групи елементарних операцій: списання з рахунку К суми коштів S; зарахування суми коштів S на рахунок D.
Існують механізми відкоту змін у БД, якщо умови успішного завершення всіх елементарних операцій, які входять до складу групи, не виконані. Основним механізмів є обробка трансакцій [2, 4, 6, 7]. Звичайно обробка трансакцій реалізується в промислових БД. Однак ряд засобів розробки прикладних програм [5] дозволяють керувати трансакціями й для таблиць локальних СКБД (Paradox, dbase). Крім того, як для промислових, так і локальних систем, надається додатковий механізм управління відкотами змін у БД – так звані кешовані зміни (cached updates, що найчастіше перекладають як буферизовані зміни).
Трансакція – це дія або серія дій, що виконуються одним користувачем або прикладною програмою з метою доступу до даних або зміни вмісту БД [4].
Трансакція є логічною одиницею роботи, що виконується в БД. Вона може бути представлена окремою програмою, бути частиною алгоритму програми або навіть окремою командою (наприклад, INSERT або UPDATE) і включати довільну кількість операцій, що виконуються у БД. З погляду БД, виконання прикладної програми може розцінюватися як серія трансакцій, у проміжках між якими обробляються дані за межами БД.
Будь яка трансакція завжди має переводити БД з одного погодженого стану в інший, хоча припускається, що погодженість її стану буде порушуватися в ході виконання трансакції. Тому, будь-яка трансакція завершується одним із двох можливих способів. У разі успішного завершення її результати фіксуються (commit) у БД, і вона переходить у новий погоджений стан. Якщо виконання трансакції не є успішним, вона відміняється (rollback). Тоді у БД має бути відновлений той погоджений стан, у якому вона перебувала до початку даної трансакції. Цей процес називається відкотом (rollback) трансакції. Зафіксована трансакція не може бути скасована. Якщо виявиться, що зафіксована трансакція була помилковою, то потрібно виконати іншу трансакцію, що скасовує її дії. Таку трансакцію називають компенсуючою. Слід зазначити, що скасована трансакція може бути ще раз запущена пізніше й, залежно від причин попередньої відмови, цілком успішно завершена і зафіксована в БД.
Ніяка СКБД не має внутрішньої можливості встановити, які саме зміни мають бути сприйняті як єдине ціле, що утворює одну логічну трансакцію. Тому існує метод, що дозволяє вказувати ззовні межі кожної із трансакцій, з боку користувача. У більшості мов маніпулювання даними для визначення меж окремих трансакцій використовуються оператори BEGIN TRANSACTION, COMMIT і ROLLBACK (або їх еквіваленти). Якщо вони не були використані, то усі дії програми, що виконували зміни в БД, розцінюються як єдина трансакція. СКБД автоматично виконає команду COMMIT, якщо програма успішно завершена. В іншому випадку СКБД автоматично виконує команду ROLLBACK.
Існують чотири основні властивості трансакції (ACID – абревіатура, складена з перших літер їх англійських назв).
Атомарність. Ця властивість типу «усе або нічого». Будь-яка трансакція являє собою неподільну одиницю роботи, яка може бути або виконана вся цілком, або не виконана зовсім.
Погодженість. Кожна трансакція має переводити БД з одного погодженого стану в інший погоджений стан.
Ізольованість. Усі трансакції виконуються незалежно одна від іншої. Інакше кажучи, проміжні результати незавершеної трансакції не повинні бути доступні іншим трансакціям.
Тривалість. Результати успішно завершеної (зафіксованої) трансакції мають зберігатися в БД постійно й не повинні бути загублені в результаті наступних збоїв.
Проблеми одночасної зміни даних виникають при синхронній роботі декількох клієнтів з одним відношенням. Нехай користувач А одержав дані з відношення Books і згодом змінив їх. У цей час з тим самим рядком відношення Books працює користувач В. Він також модифікував дані в тому ж записі, що й А, і намагається підтвердити ці зміни. Користувач С працює з відношенням Books у режимі читання. Відразу ж виникає низка питань: дозволяти або не дозволяти користувачу В змінювати запис, якщо А ще не підтвердив свої зміни? Чи дозволяти користувачу С бачити зміни, внесені А та В? Чи може користувач А бачити зміни, внесені В, та навпаки?
Для вирішення зазначених проблем існує декілька рівнів ізоляції (розмежування) трансакцій: Dirty Read, Read Committed, Repeatable Read. Рівень ізоляції трансакції визначає:
чи можуть інші (конкуруючі) трансакції вносити зміни в дані, змінені поточною трансакцією;
чи може поточна трансакція бачити зміни, зроблені конкуруючими трансакціями, та навпаки.
Рівень ізоляції трансакції Dirty Read дає можливість конкуруючим трансакціям бачити зміни, які внесені але непідтверджені поточною трансакцією. Якщо поточна трансакція скасує зроблені зміни, інші трансакції будуть бачити недостовірні дані. Цей рівень ізоляції може призвести до значних помилок і застосовується мало.
Рівень ізоляції трансакції Read Committed дозволяє конкуруючим трансакціям оперувати тільки підтвердженими змінами, які зроблені у поточній трансакції.
Нехай трансакції А і В виконуються клієнтами, які корегують або читають дані одного відношення БД. Нехай трансакція А змінила дані, але не підтвердила зміни. Нехай конкуруюча трансакція В намагається зчитати ці дані. Тоді вона одержує їх у тому стані, в якім вони перебували до старту трансакції А. Іншими словами, трансакція В не бачить у відношенні змін, внесених але не підтверджених трансакцією А.
Можливий і інший варіант. Нехай трансакція А вносить зміни в дані деякого відношення й не підтверджує їх. У цей час стартує трансакція В у прикладній програмі, де не відкрите відношення, в якому трансакція А змінює дані. Тоді спроба ініціалізації трансакції В буде відхилена. Відкрити набір даних клієнт зможе лише після того, як трансакція А підтвердить зроблені зміни.
Нехай трансакції А і В започатковуються прикладними програмами, у кожній з яких відкритий набір даних, що пов'язаний з однаковим відношенням БД. Нехай трансакція А змінила дані, але не підтвердила ці зміни. Нехай конкуруюча трансакція B також внесла зміни в ті самі дані. Тоді спроба трансакції B підтвердити внесені зміни буде відхилена.
Рівень ізоляції трансакції Repeatable Read забезпечує ситуацію, під час якої поточна трансакція завжди бачить дані в тому стані, у якому вони перебували на момент її старту.
Нехай трансакція А відкрила набір даних. Після цього трансакція В внесла в ті самі дані зміни й не підтвердила їх. Тоді при повторному відкритті набору даних трансакція А одержить дані у тому стані, в якому вони перебували на момент її старту. Однак «свої» зміни трансакція А бачити буде. Нехай трансакція В підтвердила зроблені нею зміни, а трансакція А знову відкрила набір даних. І в цьому випадку трансакція А одержить дані в тому стані, у якому вони перебували на момент її старту.
Нехай трансакція А внесла зміни в дані й не підтвердила їх. Трансакція В після цього також внесла зміни в ті самі дані. Тоді спроба трансакції В підтвердити внесені нею зміни буде відхилена.
Визначення рівня ізоляції трансакцій у прикладній програмі клієнта залежить від середовища розробки. Наприклад, у прикладних програмах, які написані в середовищі Delphi або C-Bilder, рівень ізоляції трансакцій визначається властивістю компонента Tdatabase – property Translsolation: Ttranslsolation. Можливі значення: tiDirtyRead, tiReadCommitted, tiRepeatableRead. Різні сервери БД по-різному інтерпретують рівні ізоляції трансакцій, що визначені у властивості Translsolation (табл. 9.1).
Таблиця 9.1
Сервер | Рівень трансакції | Інтерпретується як |
---|---|---|
Oracle | tidirtyread tireadcommitted tirepeatableread | tireadcommitted tireadcommitted tirepeatableread (Тільки для читання) |
Sybase, MS-SQL | tidirtyread tireadcommitted tirepeatableread | tireadcommitted tireadcommitted He підтримується |
DB2, Informix, Interbase | tidirtyread tireadcommitted tirepeatableread | tidirtyread tireadcommitted tirepeatableread |
Paradox, dbase | tidirtyread tireadcommitted tirepeatableread | tidirtyread He підтримується He підтримується |
InterВase керує трансакціями за допомогою SQL-операторів SET TRANSACTION (почати трансакцію), COMMIT (підтвердити трансакцію) і ROLLBACK, (відкотити трансакцію). Оператор SET TRANSACTION має такий формат [10, 14, 15]:
SET TRANSACTION [READ WRITE | READ ONLY]
[WAIT | NO WAIT]
[[ISOLATION LEVEL] {SNAPSHOT [TABLE STABILITY] | READ COMMITTED [[NO] RECORD_VERSION]}]
[RESERVING <list of tables>
[FOR [SHARKD | PROTECTED] [READ | WRITE]], [<list of tables> ...].
READ WRITE | READ ONLY установлює рівень доступу до даних (за замовчуванням READ WRITE);
WAIT | NO WAIT визначає поведінку SQL-сервера при виникненні конфлікту відновлення запису даної трансакції з іншою трансакцією, що раніше внесла зміну в тому самому записі: WAIT (за замовчуванням) змушує дану трансакцію очікувати завершення конкуруючої трансакції; NO WAIT визначає аварійне завершення даної трансакції;
ISOLATION LEVEL визначає рівні ізоляції трансакцій на сервері (за замовчуванням SNAPSHOT);
RESERVING у рамках даної трансакції забезпечує монопольний доступ до таблиць, що наведені в одному або декількох списках. В останньому випадку кожному елементу списку таблиць відповідають такі параметри:
PROTECTED READ – конкуруючі трансакції можуть читати дані, але не можуть змінювати їх;
PROTECTED WRITE – читати дані можуть тільки трансакції з рівнями SNAPSHOT або READ COMMITTED і ніяка конкуруюча трансакція не може їх змінювати.
Стандарт ISO включає визначення моделі трансакцій, побудованої на базі двох спеціальних операторів – COMMIT і ROLLBACK. Більшість комерційних реалізацій мови SQL, у тому числі й InterВase, підтримують цю модель, яка вперше була реалізована в СКБД DB2 компанією IBM. У стандарті вказується, що в мові SQL трансакція автоматично запускається будь-яким SQL-оператором або програмою (наприклад, SELECT, INSERT або UPDATE). Зміни, що внесені в БД під час виконання даної трансакції, не будуть доступні будь-яким іншим трансакціям, які виконуються паралельно, доти, доки ця трансакція не буде явно завершена. Завершення трансакції може бути виконано одним із способів.
1. Уведення оператора COMMIT означає успішне завершення трансакції. Після його виконання, зміни, які внесені у БД, набувають постійного характеру. Після обробки оператора COMМIT уведення будь-якого ініціюючого трансакцію оператора автоматично викличе запуск нової трансакції.
2. Уведення оператора ROLLBACK означає відмову від завершення трансакції, у результаті чого відбувається відкат усіх змін, які внесені у БД при виконанні цієї трансакції. Після обробки оператора ROLLBACK уведення будь-якого ініціюючого трансакцію оператора автоматично викличе запуск нової трансакції.
3. При використанні SQL-операторів у тексті програми успішне завершення їхньої роботи автоматично викличе завершення роботи останньою трансакції, що запущена програмою до виконання, навіть, якщо оператор COMМIT для неї не був уведений явно.
4. При використанні SQL-операторів у тексті програми аварійне завершення їхньої роботи автоматично викличе відмову останньої трансакції, що виконувалася в межах цією програми.
Використання транзакцій при спільній роботі користувачів забезпечує цілісність реляційних даних за рахунок гарантованого переходу БД з одного погодженого стану в інший. Механізм транзакцій нівелює не лише програмні колізії, а й апаратні збої, які виникають, наприклад, при втраті зв’язку між клієнтом та сервером.
© Куваєв Я.Г., 2005—2023.
Всі права захищені.
Вся інформація, яка розміщена на цьому веб-сайті, призначена тільки для персонального використання і не підлягає подальшому відтворенню і/або поширенню в будь-якій формі, інакше як за письмовим дозволом Автора.