Дещо про ACID та BASE

Існує два дуже популярні “підходи” до роботи з даними (організації транзакцій)- ACID та BASE. ACID – це акронім/ініціалізм від чотирьох вимог:

  • A – atomic/atomicity (атомарність),
  • C – consistent/consistency (консистентність (у першу чергу цілісність посилань)),
  • I – isolated/isolation (ізольованість транзакцій) та
  • D – durable/durability (стійкість до пошкоджень, наприклад, якщо зникає струм).

BASE – це акронім дещо протилежного та більш реалістичного підходу:

  • BA – Basically Available (фокус на доступності даних, база даних доступна, але не усі дані в ній і не увесь час),
  • S – Soft state (“м’який стан” – це про те, що стан має підтримуватися самим користувачем та/або може бути автоматично змінений),
  • E – Eventually Consistent (це про те, що система із плином часу переходить у цілісний стан, але протягом деякого часу дані можуть бути не цілісними).

    BASE важче пояснити за ACID, можливо тому, що цей акронім спеціально створювався як антонім до ACID, а перелічені у ньому вимоги майже ніде в усій повноті не зустрічаються.
ACID та BASE як антоніми
ACID та BASE як антоніми

У цій публікації я більше сфокусуюсь на ACID, як більш знайомому мені і більш предметному та продемонструю, що обидва акроніми – це якась дурня і їм приділяється занадто багато уваги, особливо на співбесідах.

Атомарність

Почну з атомарності. Взагалі-то, транзакції саме задля атомарності і необхідні. В іншому випадку вони б не були транзакціями, а були просто декількома окремими операціями. Я прийшов до того, що окремі операції – це добре і що транзакції мені не потрібні.

Консистентність

В першу чергу мається на увазі цілісність посилань, бо поняття цілісності запису перекривається поняттям атормарності операції (так мені здається). СУБД перевіряє чи записи за всіма посиланнями (т.з. foreign key) існують та чи не дублюється у новому записі вже існуючий primary key.

Проблема у тому, що СУБД значно більше часу витрачає на забезпечення цілісності, аніж на саме збереження даних, через що пропускна спроможність зменшується. У той же час, проблеми з цілісностю можуть виникати тоді, коли ми можемо видаляти записи, або змінювати ті їх значення, які використовуються у т.з. “primary key”.

Дані ж не повинні змінюватися, бо вони – це факти, а факти – це зафіксовані нами події минулого і вони не мають змінюватися. Таким чином, необхідність у забезпеченні цілісності даних значним чином обумовлена неправильним розумінням того, що є дані.

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

Ізольованість

Ізольованість транзакцій – це про невидімість результатів виконання транзакції до тих пір, поки вона не буде виконана.

Є видимість, а є невидимість, але у ACID існує аж чотири рівні невидимості, бо найсуворіший – це найповільніший, а швідкість запису дуже важлива в високонавантажених системах.

Таким чином ізольованість важко назвати вимогою. Ми можемо говорити лише про відносну ізольованість, більшу або меншу, але не ідеальну і безкоштовну. СУБД не може організувати обробку усіх запитів в одну чергу і послідовно обробляти один за одним. Навпаки, СУБД намагається якомога сильніше розпараллелити виконання запитів і саме через це необхідна ізольованість.

Зайве підтвердження того, що якщо відмовитися від транзакцій, то світ стає набагато простішим.

Стійкість до пошкоджень

Останній принцип/вимога – це durability – стійкість до пошкоджень. Як вона досягається? Найбільш популярним в СУРБД підходом є використання WAL – write ahead log, тобто журналів до яких значно швидше пишуться самі запити, ніж дані до БД.

Якщо відбувається якась проблема, накшталт знеструмлення, то пізніше можна програти транзакції з WAL, які СУБД не встиг виконати до інціденту. Проблема у тому, що WAL не безкоштовний. Він забирає досить багато місця, а ще запис до нього збільшує загальний час обробки запиту.

Крім того, WAL живе в оперативній пам’яті і лише час від часу зливається у постійну пам’ять – HDD або SSD, що означає, що частина записів у WAL, що не була злита у постійну пам’ять всеж-таки буде втрачена. Якщо ж кожен запис у WAL зливати в постійну пам’ять, то отримаємо ще значно більший час опрацювання запитів. Самі виробники СУРБД часто рекомендують вимикати WAL для підвищення ефектівності, тобто більшості покласти на той Durability в умовах високих навантажень.

Тепер про BASE

BASE було сформульовано для розподілених систем та баз даних, в першу чергу таких, як Cassandra, кластери MongoDB та інших подібних. Ці системи дозволяють обробляти запити не очікуючи моменту, коли всі екземпляри будуть мати однакову копію даних. Крім того, в них закладено механізми автоматичного видалення застарілих даних (частково від цього і soft state). От власне і все. 

Коли вас на співбесідах запитують про ACID і BASE – то це запитання про дуже теоретичні, ідеальні речі, які на практиці реалізовані досить брутально, не ефективно, досить часто неправильно та з концептуально неправильних міркувань.

Загалом, готові СУБД рішення – це рішення для всіх, а рішення для всіх – це рішення ні для кого конкретно. Ми їх використовуємо тому що не бажаємо довго розмірковувати та займатися дизайном інформаційної системи, крім того, мало хто на це здатен і має досить глибокі знання для цього.

Leave a Reply

Your email address will not be published. Required fields are marked *