advanced
Transactions
Сохраняйте business invariants across multiple data access calls через isolation, retries и clear transaction scope.
Транзакции ORM группируют несколько чтений и записей в одну транзакцию БД. Используйте их для защиты бизнес-инвариантов — не как обёртку вокруг каждого HTTP-запроса по умолчанию.
await db.transaction(async (tx) => {
const balance = await tx.account.findForUpdate(id);
if (balance.amount < transfer) throw new Error('insufficient');
await tx.account.debit(id, transfer);
await tx.account.credit(targetId, transfer);
});
На интервью: scope, аномалии изоляции, retries, outbox для сообщений и избегание сетевых вызовов под блокировками.
Типовые ошибки: длинные транзакции и contention; вызовы платёжек или брокеров внутри DB-транзакции; retry без идемпотентных ключей.
Компромисс — гарантии корректности против времени удержания блокировок и давления на пул соединений.
Чеклист:
- Определите защищаемый инвариант.
- Держите время блокировки коротким.
- Планируйте retries и побочные эффекты.
- Разделяйте commit БД и внешние вызовы.