弹簧事务边界和数据库连接保持

2022-09-02 22:01:25

我正在使用弹簧靴并在jpa上使用tomcat连接池进行休眠。你能帮我了解spring在交易过程中如何使用数据库连接吗?例如,请考虑以下方案:

  1. 我们有 2 个连接的 DB 连接池。
  2. Spring启动一个事务,即用@Transactional注释装饰的调用方法。
  3. 此方法执行数据库更新
  4. 调用外部服务
  5. 当从外部服务接收响应时,它会更新 DB 并返回。
  6. Spring 提交事务

假设外部服务(步骤 4)需要 1 分钟才能完成,则数据库池中将有多少个数据库连接可用?。假设 spring 会一直保持 DB 连接,直到事务完成,在此期间收到的任何请求都只有 1 个 DB 连接可用,如果我们收到 1 个以上的请求,他们将不得不等待 DB 连接。

请确认我的理解,如果正确,建议我如何在高交易量系统中处理这种情况。

谢谢


答案 1

首先,你的理解是正确的。请参阅有关声明性事务管理的春季文档。

enter image description here

我猜您在事务中执行外部服务调用,因为您希望在发生异常时回滚数据库更改。换句话说,您希望数据库更新反映外部服务调用的状态。

如果是这样,则无法将其移出事务边界。在这种情况下,您应该增加连接池大小,或者可以将长时间运行的事务委托给处理它们的专用服务器节点。例如,这将使处理用户请求的“主”服务器节点远离长时间运行的事务。

您应该考虑数据一致性。数据库更新是否真的必须与外部服务调用同步?是否可以将外部服务调用移出事务边界?


答案 2

您可以根据需要指定连接池的初始大小和最大大小(取决于应用程序的性能)。

例如

<bean id="springDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
   <property name="url" value="jdbc:oracle:thin:@localhost:1521:SPRING_TEST" />
   <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
   <property name="username" value="root" />
   <property name="password" value="root" />
   <property name="removeAbandoned" value="true"/>
   <property name="initialSize" value="20" />
   <property name="maxActive" value="30" />
</bean>

这将创建 20 个数据库连接,因为 initialSize 为 20,如果需要,则最多可达 30 个数据库连接,因为 maxActive 为 30。您可以使用 Apache DBCP 库提供的不同属性来自定义数据库连接池。上面的例子是使用Oracle 11g数据库创建连接池,我正在使用oracle.jdbc.driver.OracleDriver附带ojdbc6.jar或ojdbc6_g.jar


推荐