禁用Hibernate本地事务自动提交可大大提高性能

18-09-03 banq
              

将数据库连接配置的自动提交auto-commit关闭,

使用Spring/Spring Boot框架连接数据库时,如果使用的是非JTA事务,也就是JDBC事务,称为resource-local本地资源事务,应该将连接池(例如HikariCP)中的自动提交禁止,同时配置Hibernate如下配置属性,这样能够延迟Hibernate的连接获取时间,大大提高性能:

<property name="hibernate.connection.provider_disables_autocommit"    value="true"/>
<p>

在Hibernate中,数据库连接获取以及连接释放与当前正在运行的事务的类型有关:

1. resource-local本地资源:适用于JDBC事务,针对一个DataSource,当事务开始,Connection立即获取;在事务结束时关闭(提交或回滚也是)

2. JTA:适合XA事务,可跨越多个DataSource(s),Connection是在第一次执行SQL语句 时获得,每条语句执行后释放。如果底层应用服务器允许,可以忽视这种积极的连接释放机制。

我们的目标是使资源本地事务像JTA一样延迟Connection的获取,直到Hibernate需要执行第一条JDBC语句。

为什么Hibernate会立即获得Connection呢?因为Hibernate需要获得Connection以后检查底层JDBC Connection的自动提交状态,如果Connection设置为自动提交,Hibernate要去禁用它,并确保SQL语句在同一数据库事务的上下文中执行,虽然这种行为是正确的,因为Hibernate如果不获得Connection就无法知道自动提交标志是否已设置。

我们可以提示Hibernate跳过此检查,因为我们已经知道所有JDBC Connection(s)都以手动提交模式运行。所有企业应用程序都已使用连接池,可在数据库连接建立第一时间内禁用自动提交模式。

HikariConfig hikariConfig = super.hikariConfig( dataSource );
hikariConfig.setAutoCommit( false );
<p>

出于这个原因,Hibernate 5.2.10引入了hibernate.connection.provider_disables_autocommit配置属性,该属性告诉Hibernate:底层的JDBC Connection(s)已经禁用了自动提交模式。

性能对比有很大提高

Why you should always use hibernate.connection.pro