基于hibernate的spring-data-jpa的并发性能优化配置
摘要
默认情况下,spring-data-jpa
使用hibernate
作为jpa
的实现, 当并发量较大时, 由于框架的一些默认配置可能会引发性能瓶颈,
下面将介绍一些常见的配置项来改善并发量较大时的性能问题.
禁用open-in-view
在spring-boot
中默认开启了open-in-view
,这个配置项的作用是在整个请求上下文复用同一个EntityManager
.
该实现的好处是避免在同一个请求中多次创建一个EntityManager
, 从而提高性能.
当系统并发较大时且系统相应较慢, 由于EntityManager
会持有数据库链接直到整个请求处理完成, 如果没有特别的需求, 例如:
- 在
View
层使用Entity对象中cascade
为lazy
的关联对象
可以考虑禁用open-in-view
来提高性能
解决方案
在application.yml
中添加如下配置:
spring:
jpa:
open-in-view: false
覆盖hibernate.connection.handling_mode
配置项的默认配置
hibernate.connection.handling_mode
用于配置EntityManager
中关联的数据库连接(创建及销毁时机)的控制.
默认值创建时机为第一次与数据库交互, 关闭时机为EntitiyManager
被关闭, 此举的目的是为了确保数据连接的最大化利用(
因为数据库连接的创建通常比较昂贵).
但是对于带用DataSource
的应用来说, 此配置并不会改善性能问题, 因为DataSource
存在的意义就是复用数据库连接.
并且由于EntityManager
关联的数据库连接只有在关闭时才会被释放, 如果遇到EntityManager
长时间存活时并且此时系统并发较大会导致数据库没有空闲的连接导致后续请求被堵塞甚至获取数据库连接超时.
为了解决这个问题, 可以考虑配置hibernate.connection.handling_mode
配置项对应的值,
该配置对应的枚举类为PhysicalConnectionHandlingMode
, 枚举类中有如下几个值
对于没有使用DataSource
的应用来说, 可以考虑以下几个值, 这几个值都是为了确保数据库连接的最大化利用, 因为创建数据库连接比较昂贵.
- IMMEDIATE_ACQUISITION_AND_HOLD
表示连接会在EntityManager
创建时获取, 关闭时释放.
该配置的目的是为了能够在整个请求上下文中复用同一个数据库连接, 因为创建数据库连接比较昂贵. 但是对于带用DataSource
的应用来说, 此配置并不会改善性能问题, 因为DataSource
存在的意义就是复用数据库连接. - DELAYED_ACQUISITION_AND_HOLD
表示连接会EntityManager
和数据库产生交互时获取, 关闭时释放. 这是默认的配置.
此配置和上面的配置除了获取连接的时机不同外, 其他都相同.
对于使用DataSource
的应用来说, 可以积极地释放数据库链接来提高系统吞吐率, 因为DataSource
已经帮我们做了数据库连接的复用,
- DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
如果需要执行多个独立的语句,那么可以选择此配置 - DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION
如果应用程序需要执行多个事务,并且不在乎事务的一致性,那么可以选择此配置.
这个配置一个潜在的问题是由于事务提交前会释放数据库连接, 如果后续事务提交时需要获取数据库连接时出现了问题会导致事务提交失败, 从而导致数据库中的事务一直处于开启状态 - DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION
如果需要处理事务, 并且为了保证事务的一致性, 那么可以选择此配置
一般来说, 如果应用程序需要处理事务, 并且为了保证事务的一致性,
那么可以选择DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION
配置.
如果应用不在乎事务的一致性, 那么可以选择DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION
配置,
由于此配置会在事务提交前释放数据库连接,有可能会导致后续事务提交时获取数据库连接失败, 从而导致事务提交失败,
从而导致数据库中的事务一直处于开启状态, 所以此配置需要谨慎使用.
如果应用不需要处理事务, 那么可以选择DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
配置.
解决方案
在application.yml
中添加如下配置:
spring:
jpa:
properties:
hibernate:
connection:
handling_mode: your_handling_mode
总结
参考资料
Open In View
Connection Control
- How does aggressive connection release work in Hibernate
- Connection handling
- PhysicalConnectionHandlingMode
- AvailableSettings