Ответ
ACID — это акроним, описывающий четыре ключевых свойства, которые гарантируют надежность транзакций в базах данных.
Atomicity (Атомарность): Гарантирует, что транзакция будет выполнена целиком или не выполнена вовсе. Не может быть промежуточного состояния. Если хотя бы одна операция внутри транзакции завершается сбоем, все предыдущие операции этой транзакции откатятся.
Consistency (Согласованность): Транзакция переводит базу данных из одного корректного состояния в другое корректное состояние. Все правила и ограничения данных (constraints, triggers) должны быть соблюдены. Например, при переводе денег со счета на счет, общая сумма денег в системе должна остаться неизменной.
Isolation (Изолированность): Параллельно выполняющиеся транзакции не должны оказывать влияния друг на друга. Результат параллельного выполнения должен быть таким же, как если бы они выполнялись последовательно. Для управления этим существуют уровни изоляции (например,
Read Uncommitted
,Read Committed
,Repeatable Read
,Serializable
).Durability (Долговечность): Если транзакция успешно завершена (закоммичена), то сделанные ею изменения сохранятся даже в случае сбоев системы (например, отключение питания). Это достигается за счет записи изменений в энергонезависимую память (например, на диск в журнал транзакций).
Пример реализации атомарности в Go с помощью sql.Tx
:
// db - это ваше соединение с БД (*sql.DB)
// Начинаем транзакцию
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
// defer tx.Rollback() — это идиоматический способ гарантировать откат,
// если что-то пойдет не так. Commit в конце отменит этот defer.
defer tx.Rollback()
// Операция 1: списание средств
_, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
if err != nil {
// Если здесь ошибка, defer tx.Rollback() сработает и отменит транзакцию
return err
}
// Операция 2: зачисление средств
_, err = tx.Exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
if err != nil {
// Если здесь ошибка, defer tx.Rollback() сработает и отменит транзакцию
return err
}
// Если все операции успешны, фиксируем транзакцию
err = tx.Commit()
if err != nil {
return err
}
// Транзакция успешно завершена