Какие существуют уровни изоляции транзакций? Опишите каждый и приведите пример установки в Go.

Ответ

Уровни изоляции транзакций — это настройка в СУБД, которая определяет, насколько одна транзакция "видит" изменения, сделанные в других параллельных транзакциях. Стандарт SQL определяет 4 уровня:

  1. Read Uncommitted (Чтение незафиксированных данных): Самый слабый уровень. Транзакция может читать данные, которые еще не были зафиксированы (не прошел COMMIT) другой транзакцией. Это может привести к проблеме "грязного чтения" (Dirty Read).

    • В PostgreSQL этот уровень работает как Read Committed.

  2. Read Committed (Чтение зафиксированных данных): Уровень по умолчанию в большинстве СУБД (включая PostgreSQL). Транзакция видит только те данные, которые были зафиксированы до ее начала. Защищает от "грязного чтения", но подвержен проблемам "неповторяемого чтения" (Non-Repeatable Read) и "фантомного чтения" (Phantom Read).



  3. Repeatable Read (Повторяемое чтение): Гарантирует, что если транзакция повторно читает одни и те же строки, она получит те же самые данные. Защищает от "грязного" и "неповторяемого" чтения, но все еще возможны "фантомы" (когда другая транзакция добавляет новые строки, подходящие под условие выборки).



  4. Serializable (Сериализуемый): Самый строгий уровень. Гарантирует, что результат параллельного выполнения транзакций будет таким же, как если бы они выполнялись последовательно. Защищает от всех вышеперечисленных проблем. Этот уровень может значительно снизить производительность из-за блокировок.


Установка в SQL:

BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- ваши SQL-операции
COMMIT;

Установка в Go с помощью пакета database/sql:

Это делается при старте транзакции через sql.TxOptions.

// ctx - это context.Context
// db - это *sql.DB

// Устанавливаем уровень изоляции Repeatable Read для транзакции
tx, err := db.BeginTx(ctx, &sql.TxOptions{
    Isolation: sql.LevelRepeatableRead,
    ReadOnly:  false, // транзакция на чтение и запись
})
if err != nil {
    // обработка ошибки
}
// ... работа с транзакцией tx ...

// tx.Commit() или tx.Rollback()

Выбор уровня — это всегда компромисс между согласованностью данных и производительностью системы.