Подтвердить что ты не робот

Spring транзакция REQUIRED vs REQUIRES_NEW: откат транзакции

У меня есть метод, который имеет свойство транзакции propagation = Propagation.REQUIRES_NEW:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(final UserBean userBean) {
    //Some logic here that requires modification in DB
}

Этот метод можно вызывать несколько раз одновременно и для каждой транзакции, если возникает ошибка, чем она откатывается (независимо от других транзакций).

Проблема заключается в том, что это может заставить Spring создавать несколько транзакций, даже если они доступны, и могут вызвать некоторые проблемы с производительностью.


Java doc propagation = Propagation.REQUIRED говорит: Support a current transaction, create a new one if none exists.

Это, похоже, решает проблему производительности, не так ли?

Как насчет проблемы с откатом? Что делать, если вызов нового метода откатывается при использовании существующей транзакции? не будет ли откат всей транзакции даже предыдущими вызовами?

[EDIT] Я думаю, мой вопрос был недостаточно ясным:

У нас есть сотни клиентов, подключенных к нашему серверу.

Для каждого клиента, естественно, необходимо отправить отзыв о транзакции (OK или исключение → откат).

Мой вопрос: если я использую REQUIRED, означает ли это только одна транзакция, а если 100-й клиент сталкивается с проблемой, первая транзакция клиента также откатится?

4b9b3361

Ответ 1

Использование REQUIRES_NEW только тогда, когда метод вызывается из транзакционного контекста; Когда метод вызывается из нетранзакционного контекста, он будет вести себя точно так же, как REQUIRED - он создаст новую транзакцию.

Это не означает, что для всех ваших клиентов будет только одна транзакция - каждый клиент будет запускаться из @Transactional контекста, и как только обработка запроса достигнет @Transactional, он создаст новую транзакцию.

Итак, имея это в виду, если использование REQUIRES_NEW имеет смысл для семантики этой операции - чем бы я не беспокоился о производительности - это было бы преждевременной оптимизацией учебника - я бы предпочел подчеркнуть правильность и целостность данных и беспокоиться о производительности, как только показатели производительности были собраны, и не раньше.

При откате - использование REQUIRES_NEW заставит начать новую транзакцию, поэтому исключение откатит эту транзакцию. Если есть и другая транзакция, которая также выполнялась - она будет или не будет откатываться в зависимости от того, является ли исключение пузырьком в стеке или перехватывается - ваш выбор, исходя из специфики операций. Кроме того, для более глубокого обсуждения транзакционных стратегий и отката я бы рекомендовал: "Стратегии транзакций: понимание подводных камней транзакций", Марк Ричардс.

Ответ 2

Если вам действительно нужно сделать это в отдельной транзакции, вам нужно использовать REQUIRES_NEW и жить с накладными расходами. Следите за мертвыми замками.

Я предпочел бы сделать это по-другому:

  • Подтвердить данные на стороне Java.
  • Запустите сборку в одной транзакции.
  • Если что-то пойдет не так на стороне БД → это основная ошибка БД или дизайн проверки. Отбросьте все и выбросьте критическую ошибку верхнего уровня.
  • Напишите хорошие модульные тесты.