'forUpdate().fetchAny(condition)' 只锁定一行还是多行?

Will 'forUpdate().fetchAny(condition)' lock only one row or multiple rows?

最近我已经切换到新位置的 Java 堆栈,我在使用 Jooq 时遇到了一些麻烦,它用于访问 db

我的问题是: 下面代码中的 ForUpdate 将仅阻止满足 another_condition 的一行并将被选中或满足 some_condition[=18= 的多行]

dslContext().select()
.from(my_table)
.where(some_condition)
.forUpdate()
.skipLocked()
.fetchAny(another_condition)

客户端ResultSet阅读

ResultQuery.fetchAny() 方法只定义了 jOOQ 和 JDBC 之间的客户端行为。它继续从基础 JDBC ResultSet 中获取 至多 一条记录。简而言之:

  • ResultQuery.fetchAny()ResultSet
  • 中获取第一条记录(如果可用)
  • ResultQuery.fetchOne()ResultSet 获取第一条记录(如果可用)并尝试获取另一条记录,如果它抛出 TooManyRowsException
  • ResultQuery.fetchSingle()ResultSet 中获取第一条记录,如果没有找到这样的记录则抛出 NoDataFoundException,并尝试获取另一条记录,如果抛出 TooManyRowsException

这些方法不会向服务器传达任何有关预期结果集使用的信息,因此服务器不知道您打算做什么。

服务器端锁定

这与您如何使用 SQL 悲观锁定子句无关,例如 FOR UPDATE SKIP LOCKED,这是一种纯粹在服务器端发生的操作,理想情况下是在满足您的整个数据集上WHERELIMIT 等子句。即使情况并非如此,最好直接在 SQL.[=29= 中非常明确地说明您对 SQL 查询 的了解]

那么,既然您只打算获取一条记录,为什么不使用 LIMIT 1 告诉服务器?

dslContext()
    .select()
    .from(my_table)
    .where(some_condition)
    .limit(1)
    .forUpdate()
    .skipLocked()
    .fetchOne();

API 旁注

请注意,无法将 "another_condition" 传递给 fetchAny()。您可能打算流式传输结果并在其上使用 Stream.filter() 或类似的东西?但是为什么要锁定 N 条记录并丢弃其中的大部分?