按请求变量事务隔离级别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按请求变量事务隔离级别相关的知识,希望对你有一定的参考价值。

我正在写一个小小的拍卖应用程序,我的出价肯定会被记录下来非常重要。毕竟,拍卖的最后几秒是买家的关键时刻,我不能冒险同时竞标和竞争条件。

当然,这就是事务隔离的目的。我可以将我的隔离级别设置为可序列化,我们都已设置好。

但是所有其他要求呢?如果人们正在查看配置文件或发送消息,则这些请求不需要接近那种事务隔离。读提交隔离级别对于这些请求是完全可接受的。

我将我的事务级别设置为我的hibernate属性hibernate.connection.isolation的一部分,但我真的希望能够按照请求执行类似session.setTransactionIsolation(newIsolation)的操作。

答案
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;
}
另一答案

如果您使用的是Spring,可以使用以下内容:

@Transactional(isolation = Isolation.SERIALIZABLE)

it works for the JpaTransactionManager。如果您使用的是JtaTransactionManager,则不会传播请求范围事务隔离,因为这是默认的JTA行为。

由于JTA不支持事务范围的隔离级别,因此Spring在使用应用程序服务器JTA DataSource时提供了IsolationLevelDataSourceRouter来克服这个缺点。

因为大多数DataSource实现只能采用默认的事务隔离级别,所以我们可以拥有多个这样的DataSource,每个DataSource为特定的事务隔离级别提供连接。

逻辑事务(例如@Transactional)隔离级别设置由IsolationLevelDataSourceRouter进行内省,因此连接获取请求被委托给可以为具有相同事务隔离级别设置的JDBC连接提供服务的特定DataSource实现。

因此,即使在JTA环境中,事务隔离路由器也可以提供独立于供应商的解决方案,以便在每个事务的基础上覆盖默认数据库隔离级别。

Java EE不支持方法级事务隔离配置。

SERIALIZABLE隔离级别将保护您免受不可重复的读取和幻像读取,甚至SERIALIZABLE也不会保护您against lost updates across multiple-request logical transactions

当使用分离的实体时,Optimistic locking会更好地扩展(当逻辑事务开始时它们被加载)。

另一答案

对于这种情况,我将在您的出价对象中使用Optimistic lock ...竞争条件仍将发生,但是当事务尝试在您的域对象上提交更改时将检测到它(如果已更新的版本被更新,则抛出异常)另一个线程)。

因此,对任何投标对象的任何更改都将几乎可序列化(我说“几乎”因为为了可序列化,失败的事务将需要被捕获并以某种方式重试)。

另一答案

如果设置每个事务的隔离级别失败,您始终可以在代码中手动序列化特定操作(同步,信号量等)。但请注意,它不可扩展(单个jvm,单个操作,很容易被代码的其他部分意外地绕过)

以上是关于按请求变量事务隔离级别的主要内容,如果未能解决你的问题,请参考以下文章

事务隔离级别

事务的隔离级别

如何使用 DBUnit 设置事务隔离级别

MySQL事务隔离级别

隔离级别不保证 ORACLE Sql 上的事务存在

深入了解mysql锁机制与事务的隔离级别