Задержка между завершением транзакции Spring @и фактической фиксацией БД

#spring #spring-boot #docker #transactions #spring-transactions

#весна #пружинный ботинок #докер #операции #весна-сделки

Вопрос:

У меня есть простое приложение SpringBoot, которое использует SpringData и имеет следующую структуру SlotConfigsController -gt; Репозиторий (CrudRepository)

 @RestController @RequiredArgsConstructor public class ConfigsController {  private final ConfigsRepository configsRepository;   @PostMapping(path = "/configs")  public ResponseEntitylt;Voidgt; saveConfig(@RequestBody ConfigDto config) {  ConfigEntity config = CONFIGS_MAPPER.dtoToEntity(config);  configsRepository.save(config);  log.info("Transactional method finished");  } }  

Хранилище

 @Repository public interface ConfigsRepository extends CrudRepositorylt;ConfigsEntity, Longgt; {  @Transactional  ConfigsEntity save(ConfigsEntity entity); }  

Я запустил базу данных Postgres с помощью docker-compose и включил журналы через

 environment:  - EXTRA_CONF=log_statement=all  

Что я заметил во время анализа журнала, так это то, что фактическая фиксация БД (внутри журнала docker) происходит после log.info(...) вызова.
Вот журнал из кода

 17:12:11,856 TRACE [http-nio-8080-exec-2] [TransactionSynchronizationManager.java] - Clearing transaction synchronization  17:12:11,856 TRACE [http-nio-8080-exec-2] [TransactionSynchronizationManager.java] - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@550de51c] for key [HikariDataSource (Hikari)] from thread [http-nio-8080-exec-2] 17:12:11,856 TRACE [http-nio-8080-exec-2] [TransactionSynchronizationManager.java] - Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@6752dcc] for key [public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object)] from thread [http-nio-8080-exec-2] 17:12:11,857 INFO [http-nio-8080-exec-2] [SlotConfigsController.java] - Transactional method finished 17:12:11,863 TRACE [http-nio-8080-exec-2] [TransactionSynchronizationManager.java] - Removed value [org.springframework.orm.jpa.EntityManagerHolder@4ecd9132] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@2210e466] from thread [http-nio-8080-exec-2]  

А вот журнал базы данных docker

 17:12:11.871 UTC [555] test@test LOG: execute lt;unnamedgt;: update public.slot_configs set close_time=$1 where slot_config_id=$2 17:12:11.871 UTC [555] test@test DETAIL: parameters: $1 = '1630', $2 = 5 17:12:11.877 UTC [555] test@test LOG: execute S_2: COMMIT  

В 17:12:11 857 мы вышли из транзакционного CrudRepository.save метода, но реальная вставка данных в БД и фиксация транзакции происходят только в 17:12:11.871 — 17:12:11.877

Я предполагал, что, когда @Transactional метод будет завершен, данные уже должны быть в БД, но, похоже, это действие асинхронно. Я также пытался создать службу между контроллером и репозиторием и пометить метод сохранения в службе как @Transactional(propagation = Propagation.REQUIRES_NEW) , но это ничего не меняет. Все еще существует задержка между транзакциями кода и фактическими транзакциями в БД.

Почему это происходит? И можно ли сказать Spring, чтобы дождаться фиксации транзакции БД перед выходом из @Transactional метода?

Комментарии:

1. Ваше понимание неверно. Транзакция будет зафиксирована после @Transactional ее завершения. Это ваша транзакционная граница. В основном происходит запуск транзакции -gt; gt; метод выполнения службы -gt; gt; фиксация транзакции . Нет фиксации где-то между вашими методами при вызове службы. Так что все работает так, как задумано. Таким образом, фиксация происходит после вызова log.info .

2. В контроллере нет никаких @Transactional аннотаций. Только метод сохранения помечен как @Transactional . Итак, после завершения save метода мы уже вышли из нашей транзакции, и мы перешли к следующей строке кода log.info , позвольте мне отредактировать классы, чтобы это было более понятно.

3. Также другое дело, что вы синхронизируетесь по меткам времени, если эти часы не совпадают, у вас все равно не будет соответствующей временной шкалы. Сопоставление/сопоставление журналов с метками времени проблематично, имхо (и опыт). Параметр @Transactional on save не добавляет ничего, что save уже делает метод по умолчанию. Наконец, отключите режим открытой сессии, так как это также может повлиять на ситуацию.

4. @M. Deinum, спасибо, я добавил @Transactional метод сохранения только для ясности (я понимаю, что это ни на что не влияет). Что касается отключенной открытой сессии в поле зрения- спасибо! Я не знал об этом, проверяя сейчас. Кстати, в случае, если временные метки не рекомендуются, может быть, есть предложения с вашей стороны?

5. Если есть хоть малейшее отклонение между часами или что-то в этом роде, ваша регистрация будет отключена. Вы хотите включить промежуток и т. Д. Что-то вроде того, что предоставляет OpenTrace/Zipkin.