Управління транзакціями 1
Транзакція - (англ. Transaction) - група послідовних операцій з базою даних, яка являє собою логічну одиницю роботи з даними. Транзакція може бути виконана або цілком і успішно, дотримуючись цілісність даних і незалежно від паралельно йдуть інших транзакцій, або не виконана взагалі і тоді вона не повинна призвести ніякого ефекту. Транзакція переводить базу даних з одного несуперечливого стану в інше.
При успішному завершенні транзакція фіксується, виконується операція «commit». При виникненні збою вже виконані дії скасовуються і транзакція «відкочується», виконується операція «rollback».
Властивості, якими повинні володіти транзакції і підтримуюча їх система. Зазвичай для позначення цих властивостей використовують абревіатуру ACID - Atomicity, Consistency, Isolation, Durability. У перекладі на українську - Атомарність, Узгодженість, Ізольованість і Довговічність. Розглянемо ці властивості докладніше.
Атомарність якраз і означає неподільність транзакції і вимога або виконувати її цілком, або не виконувати взагалі.
Узгодженість - узгодженість означає ще й відповідність бази даних бізнес-правилами. Зокрема, з обмежень цілісності може слідувати заборона на негативне значення залишку на рахунку, але, скажімо, вимоги рівності списується і зараховується суми при переказі коштів з рахунку на рахунок - це вже бізнес-правило, яке за допомогою обмежень цілісності який висловити.
Ізольованість - це властивість транзакції виконуватися незалежно один від одного. Тобто, в процесі виконання однієї транзакції інші не можуть вплинути на результат її виконання. Забезпечення досконалої незалежності транзакцій один від одного вимагає і відповідних ресурсів, і негативно позначається на швидкості виконання операцій з даними, так що існує декілька, так званих, рівнів ізольованості, які будуть розглянуті далі.
Довговічність - це властивість транзакції зберігатися в системі «назавжди» після успішного завершення. Очевидно, що в процесі роботи СУБД можуть виникати збої обладнання, відключення живлення, інші помилки, але гарантується, що якщо видано повідомлення про успішне завершення транзакції, то зміни, внесені їй в дані, збережуться в будь-якому випадку і коли стан бази даних буде відновлено після збою, ці зміни нікуди не подінуться.
Восстановленіе.Е слі користувач не задіє транзакції в явному вигляді, то передбачається, що кожна операція - це окрема транзакція. Таким чином, робота кожного користувальницького додатка - це ланцюжок виконаних транзакцій. При наявності декількох користувачів (або при використанні багатопоточних додатків) ланцюжків транзакцій може бути кілька.
СУБД веде так званий журнал транзакцій, який зберігається на диску. В цей журнал вносяться записи про виконувані системою діях, перед тим, як дійсно внести зміни в дані, що зберігаються на диску. У журналі зберігаються і дані про вихідний стан записів. Саме ці дані використовуються в разі скасування транзакції для відновлення вихідного стану бази даних.
Паралельність. Проблеми паралельних транзакцій і рівні ізольованості. В
Організація паралельного доступу до даних досить нетривіальне завдання. Розглянемо проблеми, які можуть виникнути, якщо одночасний доступ до даних здійснюється довільно.
- Проблема останньої зміни. Виникає, коли дві транзакції намагаються змінити одні й ті ж дані.
- Проблема «брудного» читання. Виникає в ситуаціях, коли одна транзакція зчитує дані, змінені інший, ще не зафіксованої транзакцією. Відповідно, в разі відкату другий транзакції у першій залишаться невірні дані.
- Проблема неповторюваного читання. Виникає, коли одна транзакція неодноразово зчитує дані, а інші транзакції їх в цей час змінюють.
- Проблема читання «фантомів». Виникає, коли транзакція зчитує дані кілька разів, а інша (або інші) транзакції їх в цей час додають. У підсумку, результати пізніших зчитувань будуть містити додаткові дані, «фантоми», які відповідають умовам відбору, але раніше не вибиралися.
Для того, щоб мати можливість отримати прийнятну продуктивність і мінімізувати можливі проблеми були введені рівні ізольованості. Їх чотири, і вони пронумеровані від 0 - найнижчий рівень, до 3 - найвищий.
0 - read uncommitted. На цьому рівні транзакції ізолюються найслабше. На цьому рівні можливо і «брудне» читання, і неповторяющееся читання, і читання «фантомів». Гарантується тільки відсутність втрачених оновлень - одночасний доступ декількох транзакцій до одних і тих же даних для їх зміни виключається.
2 - repeatable read. Назва цього рівня, «повторюване читання» говорить про те, що на ньому також виключається проблема неповторюваного читання. Тобто, лічені однієї транзакцією дані захищаються від зміни або видалення іншими транзакціями.
3 - serializable. Це найвищий рівень ізольованості, на український його назву можна перекласти як «впорядковує», хоча зустрічається і варіант «Серіалізуемое». На цьому рівні СУБД виконує транзакції в такому порядку, щоб результат їх паралельного виконання був еквівалентний послідовному виконанню по одній. Такий рівень виключає всі проблеми одночасного доступу до даних.
Для того, щоб забезпечити ізольованість транзакцій більшості СУБД використовується механізм блокувань. Перед тим, як почати обробляти дані, транзакція встановлює блокування, і тим самим захищає дані від небажаних змін. Існує дві основних блокування - блокування читання і блокування записи. Також їх називають S-блокування (від Shared, колективна) і X-блокування (від eXclusive - виняткова). Перед тим, як вважати необхідні дані, транзакція повинна встановити блокування читання. Блокування читання, будучи встановленої, не перешкоджає установці іншими транзакціями блокування читання, але забороняє установку блокування записи. Так виключаються ситуації неповторюваного читання. Якщо транзакції потрібно змінити якісь дані, то вона повинна встановити на них блокування записи. Це блокування забороняє встановлення будь-яких інших блокувань, так що інші транзакції не зможуть ні прочитати, ні тим більше змінити ті ж дані. Якщо транзакція, намагаючись виконати одну з операцій, стикається з блокуванням, то вона переходить в режим очікування, її виконання призупиняється до тих пір, поки не звільняться потрібні дані.
Для виявлення взаімоблокіровок можна використовувати різні підходи. У багатьох СУБД це питання вирішується через механізм тайм-аутів. Для кожної транзакції визначається час, за яке вона повинна виконатися, і якщо вона в нього не вкладається, то відбувається її відкат. Виходить, що навіть якщо виникає взаімоблокіровка, вона встановлюється на деякий невеликий проміжок часу, а потім автоматично дозволяється скасуванням однієї з транзакцій.