Транзакции
Фиксируйте и откатывайте изменения
«Транзакции» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Зачем нужны транзакции
Транзакция объединяет несколько выражений, чтобы они либо все выполнились успешно, либо все завершились неудачей. Это сохраняет согласованность данных, например при переводе денег между двумя счетами без потери средств в середине операции.
- Атомарность: либо всё, либо ничего
- Согласованное состояние
- Изоляция от других транзакций
Начало транзакции с помощью Begin
Begin начинает транзакцию и возвращает объект *sql.Tx. Выполняйте выражения в Tx, а не в пуле, чтобы они использовали одно соединение и одну транзакцию.
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}Выражения в Tx
Вызывайте tx.Exec и tx.Query так же, как для базы данных, но все операции выполняются внутри транзакции, пока Вы не зафиксируете или не откатите её.
_, err = tx.Exec("UPDATE accounts SET balance = balance - $1 WHERE id = $2", 100, 1)Commit
tx.Commit() делает все изменения постоянными и видимыми другим пользователям. Если вызов возвращает ошибку, транзакция не была применена.
if err := tx.Commit(); err != nil {
log.Fatal(err)
}Rollback
Если какой-либо шаг завершается неудачей, вызовите tx.Rollback(), чтобы отменить все изменения с момента Begin. База данных вернётся в прежнее состояние, как будто ничего не произошло.
if err != nil {
tx.Rollback()
return err
}Шаблон с отложенным Rollback
Надёжный приём — отложить Rollback сразу после Begin. Rollback после успешного Commit безвреден и ничего не делает, поэтому такой подход гарантирует освобождение ресурсов при любом пути с ошибкой.
tx, err := db.Begin()
if err != nil { return err }
defer tx.Rollback()
// ... do work ...
return tx.Commit()Пример атомарной операции transfer
Два обновления образуют одну логическую операцию: вычесть сумму с одного счёта и добавить её на другой. Оба изменения должны быть зафиксированы вместе, иначе не должно применяться ни одно.
Рабочая симуляция транзакции
Для настоящих транзакций нужна база данных. Этот запускаемый пример моделирует начало транзакции, два обновления и фиксацию или откат с помощью карты в памяти.
package main
import (
"errors"
"fmt"
)
func transfer(bal map[string]int, from, to string, amt int) error {
if bal[from] < amt {
return errors.New("insufficient funds")
}
snapshot := map[string]int{from: bal[from], to: bal[to]}
bal[from] -= amt
bal[to] += amt
if bal[from] < 0 {
bal[from], bal[to] = snapshot[from], snapshot[to]
return errors.New("rolled back")
}
return nil
}
func main() {
bal := map[string]int{"alice": 100, "bob": 20}
if err := transfer(bal, "alice", "bob", 30); err != nil {
fmt.Println("error:", err)
} else {
fmt.Println("committed:", bal)
}
}Уровни изоляции
db.BeginTx принимает параметры, включая уровень изоляции, например sql.LevelSerializable. Более высокий уровень изоляции предотвращает больше аномалий, но может снизить параллелизм.
tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})Делайте транзакции короткими
Транзакция удерживает соединение и может удерживать блокировки. Быстро выполните все операции SQL, не обращайтесь к сети и не запрашивайте пользовательский ввод внутри транзакции, а затем оперативно зафиксируйте её, чтобы уменьшить конкуренцию.
Никогда не смешивайте базу данных и транзакцию
Внутри транзакции выполняйте выражения только через tx. Вызов db.Exec использует другое соединение за пределами транзакции, поэтому такие изменения не входят в неё и не будут отменены при откате.
Быстрая проверка
Проверьте свои знания о транзакциях.
Итоги
Вы изучили транзакции:
- Begin возвращает объект *sql.Tx; выполняйте выражения в нём
- Commit сохраняет изменения; Rollback отменяет их все
- defer tx.Rollback() гарантирует освобождение ресурсов при ошибке
- BeginTx задаёт изоляцию; делайте транзакции короткими
- Не смешивайте операции базы данных и транзакции в одной транзакции
Часто задаваемые вопросы
Урок «Транзакции» бесплатный?
Да — полный текст урока «Транзакции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Транзакции»?
Фиксируйте и откатывайте изменения Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Транзакции»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.