Какое свойство ACID гарантирует, что транзакция будет выполнена либо полностью, либо не выполнена совсем?

Ответ

Это свойство называется Атомарность (Atomicity).

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

Простой аналог — банковский перевод. Операция состоит из двух действий: списание средств с одного счета и зачисление на другой. Атомарность гарантирует, что произойдут либо оба действия, либо ни одного. Не может случиться так, что деньги списались, но не зачислились.

В Go с пакетом database/sql это реализуется через объект sql.Tx:

// db - это ваше подключение к базе данных (*sql.DB)

// 1. Начинаем транзакцию
tx, err := db.Begin()
if err != nil {
    log.Fatalf("Failed to begin transaction: %v", err)
}
// defer tx.Rollback() — хороший паттерн для отката в случае паники или раннего return
defer tx.Rollback()

// 2. Выполняем операции в рамках транзакции
_, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1")
if err != nil {
    // При ошибке Rollback будет вызван через defer
    log.Printf("Failed to debit account: %v", err)
    return
}

_, err = tx.Exec("UPDATE accounts SET balance = balance + 100 WHERE user_id = 2")
if err != nil {
    // При ошибке Rollback будет вызван через defer
    log.Printf("Failed to credit account: %v", err)
    return
}

// 3. Если все успешно, фиксируем изменения
if err = tx.Commit(); err != nil {
    log.Fatalf("Failed to commit transaction: %v", err)
}

// Если Commit() прошел успешно, отложенный Rollback() вернет ошибку, которую можно игнорировать.