advanced

Transactions

Используйте multi-document transactions сдержанно, когда invariants cross documents и simpler document modeling insufficient.

Многодокументные ACID-транзакции позволяют MongoDB координировать reads и writes между коллекциями, когда инварианты пересекают документы. Они доступны на replica set и sharded cluster (с ограничениями), но должны быть последним средством после моделирования и идемпотентных workflow.

					const session = client.startSession()
try {
  await session.withTransaction(async () => {
    await accounts.updateOne(
      { _id: fromId, balance: { $gte: amount } },
      { $inc: { balance: -amount } },
      { session }
    )
    await accounts.updateOne(
      { _id: toId },
      { $inc: { balance: amount } },
      { session }
    )
    await ledger.insertOne({ fromId, toId, amount, at: new Date() }, { session })
  })
} finally {
  await session.endSession()
}
				

| Транзакции уместны, когда | Избегайте, когда | |---------------------------|------------------| | Инвариант пересекает документы и коллекции | Достаточно обновления одного документа | | Безопасно не встроить в модель | Горячий путь с высоким throughput | | Компенсации рискованнее atomicity | Долгая работа внутри txn | | Есть идемпотентные retry | Неподдерживаемые cross-shard паттерны |

Транзакции добавляют latency, lock contention и нагрузку на oplog. Snapshot read concern по умолчанию даёт согласованные reads внутри txn. Обрабатывайте `TransientTransactionError` с ограниченными retry.

На интервью: назовите инвариант, требующий atomicity, почему одного документа мало, и как держите транзакции короткими.

Типовые ошибки: длинные транзакции с блокировками; transactions по умолчанию вместо aggregate design; игнорирование shard key; отсутствие retry; ожидание exactly-once без idempotency keys.

Компромисс — корректность между документами vs throughput: транзакции покупают атомарные инварианты ценой contention и чувствительности горячих путей.

Чеклист:

  • Явно сформулируйте многодокументный инвариант.
  • Держите scope транзакции минимальным и быстрым.
  • Проектируйте идемпотентные retry с error labels.
  • Предпочитайте атомарные обновления одного документа, когда можно.