Что означает принцип ACID в контексте баз данных?

Ответ

ACID — это набор из четырех ключевых свойств, гарантирующих надежность и предсказуемость транзакций в системах управления базами данных (СУБД).

Расшифровка принципа ACID:

Свойство Описание Пример нарушения
Atomicity
(Атомарность)
Транзакция выполняется как единое целое. Либо выполняются все ее операции, либо ни одна. Недопустимо частичное выполнение. При переводе денег списались средства с одного счета, но не зачислились на другой.
Consistency
(Согласованность)
Транзакция переводит базу данных из одного валидного состояния в другое, соблюдая все бизнес-правила, ограничения целостности (constraints), триггеры. После транзакции нарушилось ограничение уникальности или внешний ключ.
Isolation
(Изолированность)
Параллельно выполняемые транзакции не должны влиять друг на друга. Результаты их работы должны быть такими, как если бы они выполнялись последовательно. Уровни изоляции (Read Uncommitted, Read Committed и др.) определяют степень этой изоляции. Феномен "грязного" чтения (Dirty Read), когда одна транзакция видит незафиксированные изменения другой.
Durability
(Долговечность)
После успешного завершения транзакции (commit) внесенные ею изменения становятся постоянными и сохраняются даже в случае сбоя системы (отключение питания, авария). После подтверждения перевода данные о нем были потеряны из-за сбоя диска.

Практический пример на SQL/JDBC:

Connection conn = dataSource.getConnection();
try {
    conn.setAutoCommit(false); // Начало транзакции (отключение auto-commit)

    PreparedStatement stmt1 = conn.prepareStatement(
        "UPDATE accounts SET balance = balance - ? WHERE id = ?");
    stmt1.setBigDecimal(1, amount);
    stmt1.setInt(2, fromAccountId);
    stmt1.executeUpdate();

    PreparedStatement stmt2 = conn.prepareStatement(
        "UPDATE accounts SET balance = balance + ? WHERE id = ?");
    stmt2.setBigDecimal(1, amount);
    stmt2.setInt(2, toAccountId);
    stmt2.executeUpdate();

    conn.commit(); // ФИКСАЦИЯ. Только здесь изменения становятся видимыми и постоянными.
    System.out.println("Транзакция успешно завершена.");

} catch (SQLException e) {
    conn.rollback(); // ОТКАТ (ROLLBACK) при любой ошибке. Все изменения отменяются (Atomicity).
    System.out.println("Транзакция откачена: " + e.getMessage());
} finally {
    conn.setAutoCommit(true); // Возвращаем режим по умолчанию
    conn.close();
}

Ответ 18+ 🔞

Слушай, а вот эта ваша ACID, она вообще реальная или как? Ну, типа, чтобы база данных не превращалась в цирк с конями, где деньги то пропадают, то из ниоткуда берутся. Ёпта, это ж просто четыре буквы, а за ними — целая философия, блядь!

ACID — это типа священный завет для транзакций, чтобы они вели себя как порядочные, а не как последние распиздяи.

Разберём по косточкам, что это за зверь:

Свойство Что значит на человеческом Что будет, если его проебать
Atomicity
(Атомарность)
Всё или нихуя. Либо транзакция проходит на ура целиком, либо откатывается к хуям, как будто её и не было. Никаких полумер. Представь: с твоего счёта деньги списали, а до получателя не дошли. Ищи-свищи, волнение ебать.
Consistency
(Согласованность)
База — не помойка. Была в одном правильном состоянии, перешла в другое правильное состояние. Все правила, связи и ограничения на месте. После операции у тебя в базе оказалось два одинаковых пользователя с одним email. Пиздец и бардак.
Isolation
(Изолированность)
Транзакции работают параллельно, но не мешают друг другу, как будто они в отдельных кабинках. Уровни изоляции — это настройка толщины стенок этих кабинок. Одна транзакция видит, как другая наполовину обновила данные (грязное чтение). Получается каша, хуй пойми что.
Durability
(Долговечность)
Раз сказал «окей, сохраняю» (commit) — значит, пришил намертво. Даже если сервер хуйнулся, питание отрубили или бегемот на диск наступил — данные должны выжить. Ты получил подтверждение перевода, а через секунду всё пропало. Доверия ебать ноль.

Ну и как это выглядит в коде, на примере перевода бабла:

Connection conn = dataSource.getConnection();
try {
    conn.setAutoCommit(false); // Говорим: "Так, щас будет серия кадров, не прерывать!"

    // Снимаем бабки с одного счёта
    PreparedStatement stmt1 = conn.prepareStatement(
        "UPDATE accounts SET balance = balance - ? WHERE id = ?");
    stmt1.setBigDecimal(1, amount);
    stmt1.setInt(2, fromAccountId);
    stmt1.executeUpdate();

    // Кладём на другой
    PreparedStatement stmt2 = conn.prepareStatement(
        "UPDATE accounts SET balance = balance + ? WHERE id = ?");
    stmt2.setBigDecimal(1, amount);
    stmt2.setInt(2, toAccountId);
    stmt2.executeUpdate();

    conn.commit(); // ВСЁ, ТОЧКА НЕВОЗВРАТА! Фиксируем. Теперь изменения — закон.
    System.out.println("Транзакция успешно завершена.");

} catch (SQLException e) {
    conn.rollback(); // ААА, ПИЗДЕЦ! Что-то пошло не так. Откатываем ВСЁ назад, как будто ничего и не было (Вот она, атомарность, сука!).
    System.out.println("Транзакция откачена: " + e.getMessage());
} finally {
    conn.setAutoCommit(true); // Возвращаем как было, чтобы не сломать логику дальше
    conn.close();
}

Вот и вся магия. Без этого — просто анархия, данные летят к чертям, а потом сиди и разбирайся, кто, кому и сколько должен. А с ACID — хоть и сложнее, зато надёжно, как швейцарские часы, блядь.