Обработка одновременных транзакций в Spring-Boot - PullRequest
0 голосов
/ 27 апреля 2019

Так что, это может показаться очень нубским вопросом, но после некоторого поиска, я не смог найти лучший подход.

Проблема: есть приложение Spring-Boot, взаимодействующее с базой данных (MySQL).Рассмотрим таблицу T1, где я не хочу иметь только одну действительную запись для каждого пользователя.Поэтому, если появляется следующая запись, она мягко удаляет (путем установки столбца delete-at) существующие строки для этого пользователя и создает новую запись.Теперь проблема возникает, когда есть несколько запросов, почти одновременно.

Мой транзакционный блок выглядит примерно так:

@Transactional
someMethod() {
    CheckIfAnyValidEntryForUser(U1);    
    SoftDeleteExistingEntries(U1);
    DoComputation();   // Takes around a second.
    InsertNewRow();
}

Теперь, если в течение короткого промежутка времени есть несколько запросов, мой код в итоге вставляет несколько допустимых записей для одного пользователя.

Поскольку строка, которую я хочу отредактировать, может не существовать раньше, поэтому я не могу выполнить Оптимистическую блокировку по номеру версии.

Думал приобрести Global-Lock для этого метода, но это увеличило мою задержку слишком сильно.

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

Это, кажется, очень распространенная проблема, так как это обычно обрабатывается?Каков наилучший подход?

1 Ответ

2 голосов
/ 27 апреля 2019

Вы можете использовать свойство isolation аннотации @Transactional и установить для этого свойства значение Isolation.SERIALIZABLE:

@Transactional(isolation= Isolation.SERIALIZABLE)

Обратите внимание, что:

Spring по умолчанию используется DEFAULT стратегия изоляции, которая использует уровень изоляции по умолчанию для базового хранилища данных.Использование SERIALIZABLE изоляции делает ваши транзакции выполненными с блокировкой на чтение, запись, диапазон;поэтому они выглядят так, как если бы они выполнялись сериализованным способом, предотвращая грязное чтение, неповторяемое чтение и фантомное чтение.

Также

Исключительно разработан для использования с распространением.REQUIRED или Propagation.REQUIRES_NEW, поскольку он применяется только к вновь начатым транзакциям.Попробуйте поменять флаг validateExistingTransactions на true в вашем менеджере транзакций, если вы хотите, чтобы объявления уровня изоляции отклонялись при участии в существующей транзакции с другим уровнем изоляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...