1. Поява ACID

Вперше абревіатура ACID з'явилася у 1983 р. у статті Тео Хаєрдера (Theo Haerder) та Адреаса Рейтера (Andreas Reuter). Для спрощення тексту та переконливості я наведу переклад фрагмента цієї статті (з невеликими скороченнями). У цьому фрагменті використовується приклад банківської транзакції, в якій гроші переказуються з одного рахунку на інший.

Концепція транзакції, що включає в наведеному прикладі всі взаємодії з базою даних між $BEGIN_TRANSACTION і $COMMIT_TRANSACTION вимагає, щоб усі дії виконувались нероздільно (indivisibly): або всі дії належним чином відображаються у стані бази даних, або нічого не відбувається. Якщо в будь-який момент часу до досягнення $COMMIT_TRANSACTION користувач вводить оператор ERROR, який містить $RESTORE_TRANSACTION, то в базі даних не відображаються жодних змін.

Для досягнення такої неподільності транзакція повинна мати наступні чотири властивості:

Atomicity (Атомарність). Транзакція повинна мати описаний вище тип "все або нічого", і, що б не сталося, користувач повинен знати, в якому стані знаходиться його транзакція.

Consistency (Узгодженість). Транзакція, що досягає свого нормального завершення (EOT – end of transaction, завершення транзакції) і тим самим фіксує свої результати, зберігає узгодженість бази даних. Інакше кажучи, кожна успішна транзакція за визначенням фіксує лише допустимі результати. Ця умова є необхідною для підтримки четвертої якості — довговічності.

Isolation (Ізоляція). Події, що відбуваються всередині транзакції, повинні бути приховані від інших транзакцій, що одночасно виконуються. Якби ця умова не виконувалася, то з причин, згаданих вище, транзакцію було б неможливо повернути до свого початку. Для досягнення ізоляції використовуються методи, які називають синхронізацією...

Durability (Довговічність). Після того, як транзакція завершилася та зафіксувала свої результати в базі даних, система має гарантувати, що ці результати переживуть будь-які подальші збої. Оскільки відсутня будь-яка область управління, що охоплює набори транзакцій, система управління базами даних (СУБД) не має жодного контролю поза межами транзакцій.

Тож користувач повинен гарантувати, що якщо система повідомляє йому про те, що щось сталося, то це "щось" дійсно сталося. Оскільки за визначенням будь-яка (успішно завершена — С.К.) транзакція є коректною, результати неминуче з'являються в некоректних транзакцій (тобто транзакцій, що містять помилкові дані), можна усунути лише відповідною "контр"-транзакцією (countertransaction).

2. Поява транзакцій

Ці чотири властивості — атомарність, узгодженість, ізоляція та довговічність (ACID) — описують основні риси парадигми транзакцій, які впливають на багато аспектів розробки систем баз даних. Тому ми вважаємо, що здатність будь-якої системи до підтримки транзакцій є пробним каменем (ACID test) якості цієї системи.

Проста програма на мові PL/1-SQL, що переказує кошти з одного рахунку на інший.


FUNDS_TRANSFER. PROCEDURE,
 $BEGIN_TRANSACTION;
 ON ERROR DO;                                   /* in case of error */
          $RESTORE_TRANSACTION,                 /* undo all work */
          GET INPUT MESSAGE;                    /* reacquire input */
          PUT MESSAGE ('TRANSFER FAILED');      /* report failure */
          GO TO COMMIT;
          END;
 GET INPUT MESSAGE;                             /* get and parse input */
 EXTRACT ACCOUNT_EBIT, ACCOUNT_CREDIT,
  AMOUNT FROM MESSAGE,
 $UPDATE ACCOUNTS                               /* do debit */
              SET BALANCE ffi BALANCE - AMOUNT
     WHERE ACCOUNTS.NUMBER = ACCOUNT_DEBIT;
 $UPDATE ACCOUNTS                               /* do credit */
              SET BALANCE = BALANCE + AMOUNT
     WHERE ACCOUNTS.NUMBER = ACCOUNT_CREDIT;
 $INSERT INTO HISTORY                           /* keep audit trail */
    <DATE, MESSAGE>;
 PUT MESSAGE ('TRANSFER DONE');                 /* report success */
COMMIT:                                         /* commit updates */
 $COMMIT_TRANSACTION;
 END;                                           /* end of program */

Я навів приклад цього коду, щоб нагадати, що по суті властивості ACID, з одного боку, можна розглядати як вимоги до будь-якої СУБД, що претендує на підтримку транзакцій, а з іншого боку — як визначення транзакції в система баз даних. Це визначення повністю відповідає життєвій практиці. Важко уявити, наприклад, щоб клієнт, який виконує банківську транзакцію (неважливо, за сприяння живої людини-операціоніста або з використанням Internet-банкінгу), не розраховував на задоволення банком усіх властивостей ACID. Банк, який не підтримує властивості ACID для своїх транзакцій, у кращому разі втратить клієнтів, а в гіршому — збанкрутує.

3. Зв'язок ACID

Дуже важливо, що властивості ACID є нероздільними, відкидання будь-якої з них робить комбінацію, що залишилася, безглуздою. Зокрема, якщо відкинути властивість узгодженості (у тому сенсі, в якому воно використовувалося в наведеній цитаті), ми втратимо критерій коректності транзакції. Система баз даних не зможе будь-яким осмисленим чином приймати рішення про допустимість або неприпустимість фіксації транзакцій, і всі перевірки коректності виконання операцій при поточному стані бази даних доведеться виконувати в коді програм.

Треба розуміти, що в цьому випадку йдеться про логічну узгодженість. Клієнту банку потрібно, щоб банк працював за встановленими ним та відомими клієнтами правилами, щоб не можна було виконувати будь-яку транзакцію, що порушує ці правила, щоб наступна транзакція того ж клієнта виконувалася в середовищі, узгодженому відповідно до цих правил.

Клієнту онлайн-магазину потрібно, щоб замовлений та оплачений ним товар був своєчасно йому доставлений (відповідно до встановлених та відомих клієнту правил). Інакше він не довірятиме цьому магазину. Водночас ані клієнту банку, ані клієнту інтернет-мазина немає діла до внутрішньої кухні підприємства, ані до того, які внутрішні дії робляться до виконання його транзакції. Клієнтові байдуже на те, як підтримується фізична узгодженість цього підприємства, яким чином виконуються операції на фізичному рівні.

Якщо турботу про підтримку логічної узгодженості транзакцій (і бази даних) бере на себе СУБД, то програми стають простішими, зрозумілими та надійними. Вся логіка прикладної області (банку, магазину, складу тощо), що стосується транзакцій та допустимого стану даних, іде в систему баз даних. І вимоги до системи дуже прості: підтримка ACID-транзакцій з урахуванням правил узгодженості, забезпеченої в базі даних додатком. На мою думку, відмова від ACID-транзакцій створює непомірні труднощі для розробників додатків, яким, хочеш не хочеш, доведеться самим реалізовувати щось схоже, щоб задовольнити природні потреби своїх клієнтів.

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

На жаль, сьогодні у багатьох випадках (особливо це властиво напряму NoSQL) люди говорять про підтримку OLTP-додатків, зовсім не уточнюючи, що за транзакції маються на увазі. Тому в цій статті я використовуватиму поєднання ACID-транзакції для позначення справжніх транзакцій, а не уточнюваний термін транзакція буде використовуватися в неформальному сенсі, різному в різних контекстах.

Займемося тепер "теоремою" CAP і постараємося розібратися, що означає узгодженість у сенсі Брювера.