Базы данных: Транзакции

11 вопросов

1 Зачем нужны транзакции?

Транзакция объединяет несколько операций в одну логическую единицу: либо выполняются все, либо ни одна (atomicity). Обеспечивает консистентность при сбоях и конкурентном доступе. Без транзакции частичное выполнение при ошибке оставляет БД в некорректном состоянии.

$pdo->beginTransaction();
try {
    $pdo->exec("INSERT ..."); $pdo->exec("UPDATE ...");
    $pdo->commit();
} catch (\Throwable $e) { $pdo->rollBack(); throw $e; }
Открыть отдельно →
2 Уровни изоляции транзакций. Что дают?

Read Uncommitted - видны незакоммиченные изменения других (грязное чтение). Read Committed - только закоммиченные; повторное чтение может вернуть другую строку (non-repeatable read). Repeatable Read - снимок на начало транзакции; в PG защита от phantom read через snapshot. Serializable - полная изоляция, как последовательное выполнение. По умолчанию в PG - Read Committed, в MySQL - Repeatable Read. Более высокий уровень - меньше аномалий, но больше блокировок/откатов.

Открыть отдельно →
3 Что такое dirty read, non-repeatable read, phantom read?

Dirty read - чтение незакоммиченных данных другой транзакции; при откате той транзакции прочитанное неверно. Non-repeatable read - в одной транзакции два чтения одной строки дают разные значения (другая транзакция закоммитила изменение). Phantom read - два чтения по одному условию возвращают разный набор строк (другая транзакция вставила/удалила подходящие строки). Read Uncommitted допускает dirty; Read Committed - non-repeatable; Repeatable Read в PG устраняет phantom за счет snapshot; Serializable устраняет все.

Открыть отдельно →
4 Что такое deadlock? Как избежать?

Взаимная блокировка: транзакция A ждет ресурс, занятый B, а B ждет ресурс, занятый A. СУБД обнаруживает deadlock и откатывает одну из транзакций (жертва). Избежание: фиксированный порядок блокировки ресурсов (всегда блокировать в одном порядке, например по id); короткие транзакции; избегать цепочек ожидания; ретраи при deadlock. Мониторинг: логирование deadlock, pg_stat_activity.

Открыть отдельно →
5 Оптимистичная vs пессимистичная блокировка?

Пессимистичная - блокируем строку/запись на время транзакции (SELECT FOR UPDATE), другие ждут. Гарантирует консистентность, но снижает параллелизм. Оптимистичная - не блокируем при чтении; при обновлении проверяем, что версия/значения не изменились (version column или WHERE condition); при конфликте - ретраи или ошибка. Меньше блокировок, подходит при низкой конкуренции. Высокая конкуренция - часто пессимистичная или явные блокировки.

Открыть отдельно →
6 Что такое SELECT FOR UPDATE?

Блокирует выбранные строки до конца транзакции. Другая транзакция с SELECT FOR UPDATE или изменением этих строк будет ждать (или откатится при nowait). Используется для пессимистичной блокировки при "прочитал-изменил-записал". FOR UPDATE SKIP LOCKED - пропускать уже заблокированные строки (очереди задач). FOR SHARE - блокировка на чтение (shared lock).

SELECT * FROM orders WHERE id = 1 FOR UPDATE;
Открыть отдельно →
7 Что такое SAVEPOINT?

Точка сохранения внутри транзакции. Можно откатиться к SAVEPOINT, не отменяя всю транзакцию. Полезно для вложенной логики: часть операций откатить, остальное оставить.

SAVEPOINT sp1;
-- операции
ROLLBACK TO sp1;  -- откат только до sp1
-- или RELEASE sp1; - убрать точку, сохранив изменения

В PHP/PDO: $pdo->exec('SAVEPOINT name'); $pdo->exec('ROLLBACK TO SAVEPOINT name');

Открыть отдельно →
8 Что такое lost update?

Две транзакции читают одну строку, обе вычисляют новое значение и записывают - последняя запись перезаписывает первую, изменения первой теряются. Решения: блокировка при чтении (SELECT FOR UPDATE), оптимистичная блокировка (version/timestamp или проверка старых значений в UPDATE), атомарное обновление (UPDATE ... SET count = count + 1) вместо read-modify-write.

Открыть отдельно →
9 Что такое write skew?

Аномалия при изоляции ниже Serializable: две транзакции читают согласованное состояние, каждая обновляет "свою" строку по прочитанным данным, результат нарушает инвариант. Пример: два врача читают дежурства, оба видят "есть еще один дежурный", оба снимают себя - никто не дежурит. Решение: Serializable изоляция или явные блокировки так, чтобы решение учитывало актуальное состояние (например, блокировка всех строк, участвующих в инварианте).

Открыть отдельно →
10 Что такое 2PC (Two-Phase Commit)?

Протокол распределенной фиксации транзакции с участием нескольких ресурсов (например, две БД). Фаза 1: координатор запрашивает всех участников "готовы ли закоммитить?" (prepare); если все да - фаза 2: координатор шлет commit. При отказе любого - всем rollback. Гарантирует атомарность в распределенной среде, но координатор и участники могут "зависнуть" при сбое (блокировки до решения). Часто заменяют на саги с компенсирующими действиями.

Открыть отдельно →
11 Что такое WAL (Write-Ahead Log)?

Журнал упреждающей записи: изменения сначала записываются в лог на диск, затем в сами данные. При сбое восстановление по WAL: повторное применение закоммиченных изменений. Обеспечивает durability. В PostgreSQL WAL используется также для репликации (streaming). Регулируется размер сегмента, checkpoint, archive_mode для бэкапов.

Открыть отдельно →
🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.