Я только что обнаружил, что мое приложение ведет себя по-разному, когда я использую оптимистическую блокировку с базой данных Postgresql или MariaDB, и мне интересно, может ли кто-нибудь объяснить, что происходит, и как я могу заставить приложение работать таким же образом с MariaDB?Я использую Postgresl 10.5 и MariaDB 10.3.10 с движком InnoDB и настройками по умолчанию.Я использую Spring Framework версии 5.1.0 и Hibernate 5.3.6.
Так что мой код выглядит так:
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Bla {
@Id
@GeneratedValue
private long id;
@Version
private long version;
private int counter;
}
У меня также есть хранилище для этой сущности и следующий метод обслуживания:
@Transactional
public int increment(long id) {
Bla bla = blaRepo.getOne(id);
bla.setCounter(bla.getCounter() + 1);
return bla.getCounter();
}
Если я вызову этот метод в нескольких потоках, я ожидаю, что обновление будет успешным только для одного из них, если они коснутся сущности с одинаковой версией.В качестве примера: если я запускаю 50 потоков с Postgres db за один прогон, я получаю 3 вызова, которые завершаются успешно, и возвращают значения 1, 2, 3, а остальные 47 завершаются ошибкой с ObjectOptimisticLockingFailureException, который является ожидаемым поведением - это то, как я хотел быприложение вести себя.
Однако, если я переключусь на MariaDB, этого не произойдет.Все 50 этих потоков успешно завершены, и я получаю одно и то же значение ответа в нескольких потоках, как если бы не было оптимистической блокировки.Например, теперь первые 5 потоков вернули 1, затем 20 из них вернули 2, а остальные 3 или 4.
Почему это происходит?Это не имеет никакого смысла - для обеих баз данных сгенерированный запрос имеет вид
update bla set counter=?, version=? where id=? and version=?
Но в Postgresql произойдет сбой правильно, а с MariaDB неожиданно получится.