Spring Boot / HikariCP @Transactional不会覆盖隔离级别

时间:2017-01-10 17:14:15

标签: sql-server spring-boot transactions spring-data hikaricp

我的应用程序在我们的SQL Server数据库中的一个流量很大的表上遇到锁定争用。我们的DBA团队建议我遵循其他团队的配置,这些配置的默认事务隔离级别设置为READ_UNCOMMITTED。然后,他们应该将隔离级别设置回READ_COMMITTED以进行插入和更新。我已经反对这样做了一段时间,因为它感觉像是一个警察,而且我已经看到整个地方的警告反对使用READ_UNCOMMITTED。但是,我的双手现在被捆绑了。

我正在使用Spring Boot,使用HikariCP并使用Spring Data存储库与我的SQL Server数据库进行交互。我允许Spring从我的application.properties自动配置我的DataSource,并且几乎没有其他配置。

我已设法在我的应用属性中设置我的默认事务隔离级别:

spring.datasource.hikari.transaction-isolation=TRANSACTION_READ_UNCOMMITTED

我已经能够通过查询事务日志,从事务条目中获取SPID并运行以下查询来验证这是否有效,现在返回“ReadUncommitted”:

SELECT CASE transaction_isolation_level 
WHEN 0 THEN 'Unspecified' 
WHEN 1 THEN 'ReadUncommitted' 
WHEN 2 THEN 'ReadCommitted' 
WHEN 3 THEN 'Repeatable' 
WHEN 4 THEN 'Serializable' 
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL 
FROM sys.dm_exec_sessions 
where session_id = @@SPID

但是,在我的一个服务中,我试图将隔离级别覆盖回READ_COMMITTED,但它没有生效。

鉴于以下内容:

从application.properties中选择

spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.transaction-isolation=TRANSACTION_READ_UNCOMMITTED

JpaConfig.java

@Configuration
@EnableJpaRepositories("my.project.repository")
@EntityScan(basePackages = "my.project.model")
@EnableTransactionManagement
public class JpaConfig {
    //DataSource configured by Spring from application.properties
}

MyService.java

@Service
public class MyService {

    @Autowired private MyRepository myRepository;

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void myMethod() {
        //Logic and call to myRepository.save()
    }
}

MyRepository.java

public interface MyRepository extends JpaRepository<MyClass, Long> {

}

我错过了什么?我没有自定义的TransactionManager,因为我允许@EnableTransactionManagement为我配置,因为到目前为止我没有发现我应该提供自己的自定义实现的任何迹象。

我已经验证了如果抛出异常,事务回滚正常发生,但我无法弄清楚为什么@Transactional注释没有像我期望的那样覆盖隔离级别。

对于它的价值,我们试图解决的根本问题是我们的SQL Server数据库上的锁争用。据我所知,在SQL Server中,即使是SELECT也会锁定表(或行?)。 DBA的第一个建议是在我的查询中添加WITH(NOLOCK)提示。我无法弄清楚我的生活如何干净地完成这项工作而不必完全废弃JPA并使用本机查询。因此,他们的解决方案是默认使用READ_UNCOMMITTED,在写入事务中明确设置READ_COMMITTED。

2 个答案:

答案 0 :(得分:0)

transactionIsolation

此属性控制从池返回的连接的默认事务隔离级别。如果未指定此属性,则使用JDBC驱动程序定义的默认事务隔离级别。仅当您具有所有查询通用的特定隔离要求时,才使用此属性。此属性的值是Connection类中的常量名称,例如TRANSACTION_READ_COMMITTED,TRANSACTION_REPEATABLE_READ等。默认值:驱动程序默认值

ref:https://github.com/brettwooldridge/HikariCP

答案 1 :(得分:0)

确保在 application.properties

中进行设置
spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider