Variable transaction isolation levels by request Variable transaction isolation levels by request database database

Variable transaction isolation levels by request


If you're using Spring you can use something like this:

@Transactional(isolation = Isolation.SERIALIZABLE)

and it works for the JpaTransactionManager. If you are using JtaTransactionManager the request-scope transaction isolation is not propagated, as this is the default JTA behavior.

Because JTA doesn’t support transaction-scoped isolation levels, Spring offers the IsolationLevelDataSourceRouter to overcome this shortcoming when using application server JTA DataSources.

Because most DataSource implementations can only take a default transaction isolation level, we can have multiple such DataSources, each one serving connections for a specific transaction isolation level.

The logical transaction (e.g. @Transactional) isolation level setting is introspected by the IsolationLevelDataSourceRouter and the connection acquire request is therefore delegated to a specific DataSource implementation that can serve a JDBC Connection with the same transaction isolation level setting.

So, even in JTA environments, the transaction isolation router can offer a vendor-independent solution for overriding the default database isolation level on a per transaction basis.

Java EE doesn't support method-level transaction isolation configuration.

The SERIALIZABLE isolation level will protect you against non-repeatable reads and phantom reads, and even SERIALIZABLE doesn't protect you against lost updates across multiple-request logical transactions.

Optimistic locking6 scales better when using the detached entities (as of they were loaded when the logical transaction has started).


Session session = getSession(dataSource, sessionFactory, Connection.TRANSACTION_SERIALIZABLE);public Session getSession(DataSource dataSource, SessionFactory sessionFactory, int isolationLevel){  // Get connection from current dataSource and set new isolation  Connection connectionWithNewIsolation = dataSource.getConnection();  connectionWithNewIsolation.setTransactionIsolation(isolationLevel);  // Get session from current sessionFactory with the new isolation  Session session = sessionFactory.openSession(connectionWithNewIsolation);  // Hibernate 4.3  //SessionFactory.openStatelessSession(Connection connection)  // Hibernate 3.6  //SessionFactory.openSession(Connection connection)  //SessionFactory.openStatelessSession(Connection connection)  return session;}


For this case, i will use Optimistic lock in your bids objects... the race condition will still occurs, but it will be detected when the transaction tries to commit the changes at your domain objects (throwing an exception if the version readed was updated by another thread).

So any change on any bid object, will be almost serializable (i say "almost" because in order to be serializable, the failed transactions will need to be catched and retried somehow).