← Назад к вопросам

Какие знаешь проблемы при записи в БД двумя микросервисами?

2.8 Senior🔥 191 комментариев
#REST API и микросервисы#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Проблемы при записи в БД двумя микросервисами

Когда несколько микросервисов пишут в одну БД, возникают серьезные проблемы с консистентностью, масштабируемостью и независимостью сервисов.

1. Race Conditions (Условия гонки)

Два микросервиса одновременно читают и пишут одинаковые данные, вызывая потерю обновлений:

int currentValue = db.query("SELECT balance FROM accounts WHERE id = ?", id);
db.update("UPDATE accounts SET balance = ? WHERE id = ?", currentValue + 100, id);

Решение: Использовать SELECT FOR UPDATE с блокировками:

@Transactional
public void updateBalance(Long accountId, BigDecimal amount) {
    Account account = db.query(
        "SELECT * FROM accounts WHERE id = ? FOR UPDATE", accountId);
    account.addBalance(amount);
    db.save(account);
}

2. Проблема жесткой связанности данных

Микросервисы не должны делить БД — это нарушает принцип независимости.

Проблемы:

  • Невозможно обновлять схему одного сервиса независимо
  • Сложности с масштабированием (горячие таблицы)
  • Сильная связанность архитектуры
  • Сложно разделить данные между регионами

3. Проблема консистентности данных

Без координации возникают нарушения бизнес-правил.

Решение: Saga Pattern для двухфазного коммита:

public class CreateOrderSaga {
    @Transactional
    public void execute(CreateOrderCommand cmd) {
        PaymentReservation reservation = paymentService.reserve(
            cmd.getUserId(), cmd.getAmount());
        try {
            Order order = orderService.create(cmd);
            paymentService.commit(reservation);
        } catch (Exception e) {
            paymentService.cancel(reservation);
            throw e;
        }
    }
}

4. Deadlocks (Взаимные блокировки)

Микросервисы блокируют друг друга, ожидая доступа к данным.

Решение: Заказываем блокировки в одном порядке:

private void transferMoney(Long fromId, Long toId, BigDecimal amount) {
    Long id1 = Math.min(fromId, toId);
    Long id2 = Math.max(fromId, toId);
    db.executeInTransaction(() -> {
        Account acc1 = db.lockForUpdate(id1);
        Account acc2 = db.lockForUpdate(id2);
    });
}

5. Проблема масштабируемости

Одна БД становится узким местом.

Решение: Database per Microservice Pattern

@Configuration
public class UserServiceDataConfig {
    @Bean
    public DataSource userDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:postgresql://db1:5432/users")
            .build();
    }
}

6. Проблема версионирования схемы

Обновление схемы БД замораживает все микросервисы.

Лучшие практики

  • Database per Microservice — каждый сервис своя БД
  • Асинхронная коммуникация через Message Broker (Kafka, RabbitMQ)
  • Saga Pattern для распределенных транзакций
  • Event Sourcing для аудита и восстановления состояния
  • CQRS для сложных сценариев
  • Компенсирующие транзакции для откатов

Парадигма микросервисов требует отказа от ACID гарантий единой БД в пользу BASE модели.