Транзакція (англ. Transaction) - група послідовних операцій, яка являє собою логічну одиницю роботи з даними.
Транзакції є одним з фундаментальних концептів всіх СУБД. Сутність транзакції полягає у зв'язуванні декількох кроків в одну операцію за принципом все-або-нічого. Внутрішні проміжні стану між кроками не помітні для інших конкуруючих транзакцій і якщо під час виконання транзакції трапиться помилка, яка завадить транзакції завершиться, то в базі даних ніяких змін зроблено не буде.
Уявімо собі систему замовлення книг на Web-сайті. Процес замовлення книг видаляє обрану вами книгу зі складу та поміщає в вашу кошик, а вартість книги списується з вашої кредитної картки. Обидва ці дії повинні або завершитися успішно, або не повинно статися ні одного з них. Якщо трапляється збій при отриманні книги зі складу, оплата не повинна бути списана з кредитної картки. Такий сценарій можна реалізувати за допомогою транзакцій.
Найбільш поширене застосування транзакцій - при внесенні і оновленні інформації в базі даних. Транзакції також можуть виконуватися під час запису повідомлення в чергу повідомлень або під час запису даних в файл або системний реєстр.
Кілька дій можуть бути частинами однієї транзакції.
Існують різні моделі транзакцій, які можуть бути класифіковані на підставі різних властивостей, що включають структуру транзакції, паралельність всередині транзакції, тривалість і т.д. Найчастіше мають на увазі традиційні транзакції, що характеризуються чотирма класичними властивостями: атомарности, узгодженості, ізольованості, довговічності (міцності) - ACID (Atomicity, Consistency, Isolation, Durability). Іноді традиційні транзакції називають ACID-транзакціями. Згадані вище властивості означають наступне.
Властивість атомарности (Atomicity) виражається в тому, що транзакція повинна бути виконана в цілому або не виконано зовсім.
Властивість узгодженості (Consistency) гарантує, що в міру виконання транзакцій дані переходять з одного узгодженого стану в інше - транзакція не руйнує взаємну узгодженість даних.
Властивість ізольованості (Isolation) означає, що конкуруючі за доступ до бази даних транзакції фізично обробляються послідовно, ізольовано один від одного, але для користувачів це виглядає так, як ніби вони виконуються паралельно.
Властивість довговічності (Durability) трактується наступним чином: якщо транзакція завершена успішно, то ті зміни в даних, які були нею зроблені, не можуть бути втрачені ні за яких обставин (навіть в разі подальших помилок).
Якщо всі оператори виконані успішно та в процесі виконання транзакції не відбулося ніяких збоїв програмного чи апаратного забезпечення, транзакція фіксується.
Фіксація транзакції - це дію, що забезпечує запис на диск змін в базі даних, які були зроблені в процесі виконання транзакції. До тих пір, поки транзакція не зафіксована, можливо анулювання цих змін, відновлення бази даних у те стан, в якому вона була на момент початку транзакції. Фіксація транзакції означає, що всі результати виконання транзакції стають постійними. Вони стануть видимими іншим транзакцій тільки після того, як поточна транзакція буде зафіксована. До цього моменту всі дані, які поставлені транзакцією, будуть "видно" користувачеві в стані на початок поточної транзакції.
Якщо в процесі виконання транзакції сталося щось таке, що робить неможливим її нормальне завершення, база даних повинна бути повернута в початковий стан. Відкат транзакції - це дію, що забезпечує анулювання всіх змін даних, які були зроблені операторами SQL в тілі поточної незавершеною транзакції.
Кожен оператор в транзакції виконує свою частину роботи, але для успішного завершення всієї роботи в цілому потрібно безумовне завершення всіх їх операторів. Групування операторів в транзакції повідомляє СУБД, що вся ця група повинна бути виконана як єдине ціле, причому таке виконання має підтримуватися автоматично.
У стандарті ANSI / ISO SQL визначені модель транзакцій і функції операторів COMMIT і ROLLBACK. Стандарт визначає, що транзакція починається з першого SQL-оператора, ініційованого користувачем або утримується в програмі. Усі наступні SQL-оператори складають тіло транзакції. Транзакція завершується одним з чотирьох можливих шляхів (рис.1):
оператор COMMIT означає успішне завершення транзакції; його використання робить постійними зміни, внесені в базу даних в рамках поточної транзакції;
оператор ROLLBACK перериває транзакцію, скасовуючи зміни, зроблені в базі даних в рамках цієї транзакції; нова транзакція починається одразу ж після використання ROLLBACK;
успішне завершення програми, в якій була ініційована поточна транзакція, означає успішне завершення транзакції (начебто використали оператор COMMIT);
помилкове завершення програми перериває транзакцію (начебто використали оператор ROLLBACK).
Існують і інші моделі транзакцій (наприклад, прийнята в Sybase). Діалект SQL Sybase включає чотири оператори обробки транзакцій:
оператор BEGIN TRANSACTION сигналізує про початок транзакції;
оператор COMMIT TRANSACTION означає успішне виконання транзакції; його сенс відповідає оператору COMMIT в моделі ANSI / ISO, однак після його використання ніяка нова транзакція не стартує;
оператор SAVE TRANSACTION встановлює точку збереження в тілі транзакції - тобто зберігає стан бази даних, досягнуте на момент використання оператора. Точки збереження іменовані, що дозволяє встановлювати кілька точок збереження в транзакції; ім'я точки збереження вказується в операторі SAVE TRANSACTION.
оператор ROLLBACK TRANSACTION виконує дві функції. Якщо в операторі вказано ім'я точки збереження, то проводиться відкат до стану бази даних, досягнутого до моменту виконання оператора SAVE TRANSACTION. Якщо ж в операторі не вказано ім'я точки збереження, то проводиться відкат змін до моменту початку транзакції (див. Рис.2).
Втрата змін відбувається в ситуації, коли дві або кілька програм читають одні й ті ж дані з бази даних, вносять в них будь-які зміни і потім намагаються одночасно записати результат за попереднім місцем. Зрозуміло, в базі даних можуть бути збережені зміни, виконані лише однією програмою. - будь-які інші зміни будуть втрачені.
Зниклі зміни. Ця ситуація може виникати, якщо дві транзакції одночасно змінюють одну і ту ж запис в БД. Наприклад, працюють два оператори на прийомі замовлень, перший оператор прийняв замовлення на 30 моніторів. Коли він запитував склад, то там значилося 40 моніторів, і він, отримавши підтвердження від клієнта, виставив рахунок і оформив продаж 30 моніторів з 40. Паралельно з ним працює другий оператор, який приймає замовлення на 20 таких же моніторів (ну вже дуже хороша модель і дешево) і, в свою чергу запросив стан складу і отримавши від початку ту ж цифру 40, він успішно оформляє замовлення для свого клієнта. Закінчуючи роботу з даним замовленням, він виконує команду Оновити (UPDATE), яка заносить 20 як залишок улюблених моніторів на складі. Але після цього, нарешті, люб'язно попрощавшись зі своїм клієнтом і запевнивши його в якнайшвидшій доставці замовлених моніторів, закінчує роботу зі своїм замовленням перший оператор і також виконує команду Оновити і заносить 10 як залишок тих же моніторів на складі. Кожен з них задоволений своєю роботою, але ми-то знаємо, що сталося. Перш за все, вони продали 50 моніторів з наявних 40 штук, і далі на складі ще числиться 10 подібних моніторів. БД тепер знаходиться в неузгоджену стані, а у фірми виникли серйозні проблеми. Зміни, зроблені другим оператором, були проігноровані програмою виконання замовлення, з якою працював перший оператор. Подібна ситуація представлена на рис. 11.5.
Очевидно, що необхідна певна дисципліна обробки транзакцій, що дозволяє усунути проблеми, описані вище і їм подібні. Така дисципліна існує і спирається на наступні правила:
(1) У процесі виконання транзакції користувач (або програма) "бачить" лише узгоджені стану бази даних. Користувач (або програма) ніколи не може отримати доступ до незафіксованим змін в даних, досягнутим в результаті дій іншого користувача (програми);
(2) Якщо дві транзакції, A і B, виконуються паралельно, то СУБД вважає, що результат буде такий же, як якщо б: - транзакція A виконувалася б першою, за нею була б виконана транзакція B; - транзакція B виконувалася б першою, за нею була б виконана транзакція A.
Ця дисципліна відома як сериализация транзакцій. Фактично вона гарантує, що кожен користувач (програма), яка звертається до бази даних, працює з нею так, як ніби не існує інших користувачів (програм), одночасно з ним звертаються до тих самих даних. Для практичної реалізації цієї дисципліни більшість комерційних СУБД використовують механізм блокувань.
Для пояснення дії механізму блокувань скористаємося Рис.3 На ньому представлені три таблиці бази даних (Замовлення. Відділення. Товар), до яких можливий доступ в процесі виконання двох транзакцій - A і B. Коли при виконанні транзакції A відбувається звернення до таблиць Замовлення і Відділення . СУБД блокує фрагмент таблиці (що мається на увазі під фрагментом - буде розповісти нижче) до тих пір, поки транзакція не буде зафіксована або скасована. Транзакція B виконується паралельно і блокує на момент свого виконання таблицю Товар. Якщо в процесі виконання транзакції B робиться спроба отримати доступ до блокованих таблиць, обробка транзакції призупиняється і поновлюється тільки після того, як транзакція А завершується і звільняє блоковані нею таблиці.