I just discovered that my application behaves differently when I use optimistic locking with a Postgresql or a MariaDB database and I am wondering if somebody can explain what happens and how could I make the application work in the same way with MariaDB? I use Postgresl 10.5 and MariaDB 10.3.10 with InnoDB engine and default settings. I use Spring framework version 5.1.0 and Hibernate 5.3.6.
So my code looks like this:
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Bla {
@Id
@GeneratedValue
private long id;
@Version
private long version;
private int counter;
}
I also have a repository for this entity and the following service method:
@Transactional
public int increment(long id) {
Bla bla = blaRepo.getOne(id);
bla.setCounter(bla.getCounter() + 1);
return bla.getCounter();
}
If I call this method on multiple threads I would expect update would succeed only for a single one of them if they touch the entity with the same version. As an example: if I start 50 thread with Postgres db in one run I get 3 calls that succeed and return the values 1, 2, 3 and the other 47 fail with an ObjectOptimisticLockingFailureException which is the expected behavior - this is how I would like the app to behave.
However, if I switch to MariaDB then this doesn't happen. All 50 of these threads are completed successfully and I get the same response value in multiple threads as if there would be no optimistic lock. For example now the first 5 threads returned 1, then 20 of them returned 2, and the rest 3 or 4.
Why this is happening? It doesn't make any sense - with both databases the query generated is
update bla set counter=?, version=? where id=? and version=?
But in Postgresql will fail correctly and with MariaDB will succeed unexpectedly.