Какие существуют уровни изоляции транзакций в базах данных? Приведите пример для PostgreSQL.

Ответ

В стандарте SQL и, в частности, в PostgreSQL, определены четыре основных уровня изоляции транзакций. Каждый следующий уровень предотвращает определенные аномалии конкурентного доступа (феномены чтения).

  1. Read Uncommitted (Чтение незафиксированных данных)

    • Позволяет читать незафиксированные ("грязные") данные других транзакций.
    • Возможные аномалии: Dirty Read, Non-Repeatable Read, Phantom Read.
    • В PostgreSQL этот уровень работает как Read Committed.
  2. Read Committed (Чтение зафиксированных данных)

    • Транзакция видит только те данные, которые были зафиксированы до ее начала. Каждый новый запрос в транзакции видит свежие зафиксированные данные.
    • Возможные аномалии: Non-Repeatable Read, Phantom Read.
    • Это уровень по умолчанию в PostgreSQL.
  3. Repeatable Read (Повторяемое чтение)

    • Гарантирует, что при повторном чтении в рамках одной транзакции данные будут теми же, даже если другие транзакции их изменили и зафиксировали.
    • Возможные аномалии: Phantom Read.
  4. Serializable (Сериализуемый)

    • Самый строгий уровень. Гарантирует, что результат параллельного выполнения транзакций будет таким же, как если бы они выполнялись последовательно. Предотвращает все аномалии.

Пример установки уровня изоляции в Go при работе с database/sql:

// Установка уровня изоляции для следующей транзакции
// Вариант 1: через SQL-запрос
db.ExecContext(ctx, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE")

// Вариант 2: через опции при старте транзакции (предпочтительнее)
tx, err := db.BeginTx(ctx, &sql.TxOptions{
    Isolation: sql.LevelSerializable, // Используем константу из пакета sql
})
if err != nil {
    log.Fatal(err)
}
// ... работа с транзакцией tx