jOOQ 是否使用不同的连接来执行不同的查询?
Does jOOQ use different connections to execute different queries?
我有一项服务可以对数据库执行一些 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个线程永远卡住了,永远不会释放。回滚也不会发生,因为恢复系统的唯一方法是重新启动它。这使数据库处于不一致状态。
我的假设是否正确?
您没有使用事务性 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();
});
我有一项服务可以对数据库执行一些 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个线程永远卡住了,永远不会释放。回滚也不会发生,因为恢复系统的唯一方法是重新启动它。这使数据库处于不一致状态。
我的假设是否正确?
您没有使用事务性 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();
});