jOOQ 是不是使用不同的连接来执行不同的查询?

Posted

技术标签:

【中文标题】jOOQ 是不是使用不同的连接来执行不同的查询?【英文标题】:Does jOOQ use different connections to execute different queries?jOOQ 是否使用不同的连接来执行不同的查询? 【发布时间】:2021-04-03 12:25:17 【问题描述】:

我有一项服务可以通过数据库执行一些 CRUD。服务使用 jOOQ。这是我的交易代码的样子:

dslContext.transaction(conf -> 
   // Query1
   dslContext.update(Tables.TABLE1).set(Tables.TABLE1.COLUMN1, column1Value).where(Tables.TABLE1.COLUMN2.eq(column2Value)).execute();
   
   // Query2
   dslContext.insertInto(Tables.TABLE2).set(record1).execute();
);

请注意,dslContext 是全局的,我们使用的是 Apache DBCP2 BasicDataSource。

在高负载时,当连接池耗尽时,所有线程都会卡住,使数据库处于只执行Query1的状态。

假设连接池大小为 N 并配置为无限期等待新线程,假设是 在 t=t0,N 个并发线程尝试在 Connection1 中执行 Query1 在 t=t1 时,这 N 个线程继续前进到 Query2,但没有从池中获得连接并无限期地等待。

由于线程被卡住,事务没有结束并且没有调用提交,因此 N 个线程永远被卡住并且永远不会释放。回滚也不会发生,因为恢复系统的唯一方法是重新启动它。这会使数据库处于不一致的状态。

我的假设正确吗?

【问题讨论】:

【参考方案1】:

您没有使用事务性 conf 引用,您使用的是外部 dslContext,这不是事务性的 - 这意味着每个语句都在其自己的事务中运行,就像您没有调用transaction() 方法。

改为这样做:

dslContext.transaction(conf -> 
   // Query1
   conf.dsl().update(Tables.TABLE1)
             .set(Tables.TABLE1.COLUMN1, column1Value)
             .where(Tables.TABLE1.COLUMN2.eq(column2Value)).execute();
   
   // Query2
   conf.dsl().insertInto(Tables.TABLE2).set(record1).execute();
);

【讨论】:

以上是关于jOOQ 是不是使用不同的连接来执行不同的查询?的主要内容,如果未能解决你的问题,请参考以下文章

在 JOOQ 中,如果我直接使用底层连接,我的事务状态是不是保持不变?

如何在jooq查询的左连接中检查记录是不是完​​全为空

如何将 MySQL JOOQ 重命名表查询范围限定为同一个数据库?

如果基于一个字段的所有行在另一个字段上具有不同的值,则 JOOQ 查询返回一个布尔值

JOOQ和资源处理

如何使用 Laravel Eloquent 在不同服务器上的多个数据库之间执行连接查询?