Найти в Дзене
Записки о Java

Транзакции в MongoDB: архитектура, реализация и пример на Spring Boot

Целевая аудитория: Java-разработчики, использующие Spring Boot и MongoDB.
Версия Java: 11
Цель статьи: разобраться, как устроены транзакции в MongoDB, когда их использовать, и как реализовать в Spring Boot с тестами и Docker. MongoDB — документно-ориентированная NoSQL-база данных. Изначально она не поддерживала транзакции, полагаясь на атомарность операций над одним документом. Однако с версии 4.0 (2018) появилась поддержка многооператорных транзакций, а с 4.2 — транзакции между коллекциями и базами данных. Но! Транзакции в MongoDB работают только в реплика-сетах (replica set) или кластерах с шардированием. Для локальной разработки можно эмулировать replica set с помощью одного узла. С версии 3.2 MongoDB использует движок WiredTiger по умолчанию. Он поддерживает: Когда вы начинаете транзакцию: ⚠️ Ограничения:Максимум 1000 изменённых документов за одну транзакцию (можно увеличить через transactionLifetimeLimitSeconds).
Транзакция не должна длиться дольше 60 секунд по умолчанию.
Нельзя
Оглавление
Рисунок: транзакции в MongoDB
Рисунок: транзакции в MongoDB

Целевая аудитория: Java-разработчики, использующие Spring Boot и MongoDB.
Версия Java: 11
Цель статьи: разобраться, как устроены транзакции в MongoDB, когда их использовать, и как реализовать в Spring Boot с тестами и Docker.

Введение

MongoDB — документно-ориентированная NoSQL-база данных. Изначально она не поддерживала транзакции, полагаясь на атомарность операций над одним документом. Однако с версии 4.0 (2018) появилась поддержка многооператорных транзакций, а с 4.2 — транзакции между коллекциями и базами данных.

Но! Транзакции в MongoDB работают только в реплика-сетах (replica set) или кластерах с шардированием. Для локальной разработки можно эмулировать replica set с помощью одного узла.

Архитектура транзакций в MongoDB: как это работает «под капотом»?

1. WiredTiger — движок хранения

С версии 3.2 MongoDB использует движок WiredTiger по умолчанию. Он поддерживает:

  • MVCC (Multi-Version Concurrency Control) — каждая транзакция видит «снимок» данных на момент своего старта.
  • Журнал (Write-Ahead Log) — все изменения сначала пишутся в журнал, затем применяются к данным.
  • Атомарные коммиты — либо все изменения применяются, либо ни одно.

2. Как работает транзакция?

Когда вы начинаете транзакцию:

  • MongoDB создаёт снимок данных (snapshot).
  • Все операции (insert, update, delete) внутри транзакции буферизуются.
  • При вызове commitTransaction():Проверяется конфликт с другими транзакциями (write-write conflict).
    Если конфликта нет — изменения записываются в журнал и применяются.
    Если есть — транзакция
    откатывается, и клиенту возвращается ошибка.
⚠️ Ограничения:Максимум 1000 изменённых документов за одну транзакцию (можно увеличить через transactionLifetimeLimitSeconds).
Транзакция не должна длиться дольше
60 секунд по умолчанию.
Нельзя использовать explain(), aggregate с $out/$merge, и некоторые другие операции.

Пример предметной области: банковский перевод

Реализуем простой перевод денег между счетами — классический пример, требующий транзакций.

Сценарий:

  1. Уменьшить баланс отправителя.
  2. Увеличить баланс получателя.
  3. Записать операцию в журнал транзакций.

Если что-то пойдёт не так — всё должно откатиться.

Реализация на Spring Boot + Java 11

1. pom.xml (добавьте зависимость)

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-mongodb</artifactId>

</dependency>

2. docker-compose.yml

Рисунок: docker-compose.yml для поднятия MongoDB локально
Рисунок: docker-compose.yml для поднятия MongoDB локально

💡 Этот docker-compose.yml запускает MongoDB в режиме single-node replica set, что необходимо для транзакций.

Запуск:

docker-compose up -d

3. Entity-классы

Рисунок: класс Account
Рисунок: класс Account
Рисунок: класс TransferLog
Рисунок: класс TransferLog

4. Репозитории

Рисунок: репозиторий AccountRepository
Рисунок: репозиторий AccountRepository
Рисунок: репозиторий TransferLogRepository
Рисунок: репозиторий TransferLogRepository

5. Сервис с транзакцией

Рисунок: сервис TransferService, часть 1
Рисунок: сервис TransferService, часть 1
Рисунок: сервис TransferService, часть 2
Рисунок: сервис TransferService, часть 2

Обратите внимание: аннотация @Transactional из spring-tx работает с MongoDB только если настроен MongoTransactionManager.

6. Конфигурация транзакций

Рисунок: класс MongoConfig
Рисунок: класс MongoConfig

7. Контроллер (опционально)

Рисунок: контроллер TransferController
Рисунок: контроллер TransferController

Заключение

  • Транзакции в MongoDB возможны, но требуют replica set.
  • Они работают на основе MVCC и write-ahead logging в движке WiredTiger.
  • В Spring Boot используются @Transactional + MongoTransactionManager.
  • Не злоупотребляйте транзакциями: если можно обойтись атомарной операцией над одним документом — делайте так.
  • Транзакции — это накладные расходы: они снижают производительность и масштабируемость.
✅ Используйте транзакции только тогда, когда реально нужна согласованность между несколькими документами.

Пример, рассмотренный в статье, можно найти по адресу:
https://github.com/ShkrylAndrei/blog_yandex/tree/main/src/main/java/info/database/mongo_account_transaction