乐观锁批量更新

发布于 2024-09-03 08:04:42 字数 269 浏览 4 评论 0原文

如何使用乐观锁进行批量更新?我正在使用 SimpleJdbcTemplate,对于单行,我可以构建更新 sql,它会增加版本列值并在 WHERE 子句中包含版本。

不幸的是,使用 Oracle 驱动程序时,结果 int[] Updated = simpleJdbcTemplate.batchUpdate 不包含行计数。所有元素均为 -2,表示行数未知。

除了单独执行所有更新之外,还有其他更高效的方法吗?这些批次平均包含 5 个项目(仅),但可能最多 250 个。

How to use optimistic locking with batch updates? I am using SimpleJdbcTemplate and for a single row I can build update sql that increments version column value and includes version in WHERE clause.

Unfortunately the result int[] updated = simpleJdbcTemplate.batchUpdate does not contain rowcounts when using oracle driver. All elements are -2 indicating unknown rowcount.

Is there some other, more performant way of doing this than executing all updates individually? These batches contain an average of 5 items (only) but may be up to 250.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

疯了 2024-09-10 08:04:42

当我在 Hibernate 工作时,我们注意到旧的 Oracle JDBC 驱动程序版本没有正确报告更新计数,这就是 Hibernate 使用乐观锁定禁用实体批量更新的原因。

然而,从 Hibernate 5 开始,这不再是默认策略,因为 JDBC 驱动程序可以更好地处理批量更新计数。

因此,对于您的情况,您需要将 Oracle JDBC 驱动程序更新到至少 12c。请注意,Oracle JDBC 驱动程序向后和向前兼容,因此您甚至可以在数据库服务器端与 Oracle 11g 一起使用它。

自 2019 年 9 月起,您甚至可以从 Maven Central 获取 Oracle JDBC 驱动程序:

<dependency>
    <groupId>com.oracle.ojdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>19.3.0.0</version>
</dependency>

我将驱动程序版本 19 与 Oracle 18 XE 一起使用,即使将批量更新与乐观锁定混合使用,它也能发挥作用。

When I was working for Hibernate, we noticed that the older Oracle JDBC Driver versions did not report the update count correctly, and that's why Hibernate used to disable batch updates for entities using optimistic locking.

However, since Hibernate 5, this is no longer the default strategy as JDBC drivers handle the batch update count better.

So, in your case, you need to update the Oracle JDBC Driver to at least 12c. Note that the Oracle JDBC Driver is both backward and forward compatible, so you can use it even with Oracle 11g on the database server-side.

Since September 2019, you can even get the Oracle JDBC Driver from Maven Central:

<dependency>
    <groupId>com.oracle.ojdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>19.3.0.0</version>
</dependency>

I'm using version 19 of the driver with Oracle 18 XE, and it works like a charm even when mixing batch updates with optimistic locking.

飞烟轻若梦 2024-09-10 08:04:42

只是在这里大声思考 - 如果驱动程序中的批处理支持存在问题,您可以尝试使用单个查询来实现相同的目的,从而使批处理的相关性降低。 (如您所知,批处理是为了避免多个查询的延迟,但即使批处理单个查询,延迟仍然存在。)

以下是如何使用单个查询实现乐观更新

  • 构建一个临时表,其中包含执行查询所需的条件。行更新,并将更新查询重写为该表上的联接。 (例如,将实时数据中的当前时间戳与临时表中的时间戳进行外连接。)如果实时数据上的时间戳尚未更新,则将从临时表中选择该行。

由于您可以使用临时表作为选择查询,因此您可以找到将更新哪些行,然后将其作为更新查询提交。 (当然,所有这些都在一个事务内。)

为了说明:

TempUpdateTable
---------------
id,        // id of the row to be updated
timestamp, // timestamp data originally fetched
data1      // data to be updated
data2
dataN

这给出了所有要更新的数据的 id,您可以存储这些数据以供以后参考

SELECT d.id FROM TempUpdateTable t JOIN YourData d 
    ON t.id=d.id WHERE t.timestamp=d.timestamp

然后可以在更新语句中使用相同的查询

UPDATE YourData
SET data=t.data1
SET data=t.data2  //etc...
FROM TempUpdateTable t WHERE t.id IN
  (SELECT d.in FROM TempUpdateTable t JOIN YourData d 
    ON t.id=d.id WHERE d.timestamp=d.timestamp)

Just thinking aloud here - if it's a problem with the batch support in the driver, you could try to achieve the same using a single query, making batching less relevant. (As you know, batching is about avoiding latency with multiple queries, but latency is still present even when batching a single query.)

Here's how you might achieve the optimistic update with a single query

  • Build a temporary table that contains the conditions necessary for a row update, and rewrite your update query to be a join on this table. (e.g. outer join the current timestamp in the live data with the timestamp in your temporary table.) If the timestamp on the live data has not been updated then the row will be selected from your temporary table.

Since you can use the temporary table as a select query, you can find which rows would be updated, and then submit this as an update query. (All within a transaction, of course.)

To illustrate:

TempUpdateTable
---------------
id,        // id of the row to be updated
timestamp, // timestamp data originally fetched
data1      // data to be updated
data2
dataN

This gives the ids of all data to be updated, which you can store for later reference

SELECT d.id FROM TempUpdateTable t JOIN YourData d 
    ON t.id=d.id WHERE t.timestamp=d.timestamp

The same query can then be used in an update statement

UPDATE YourData
SET data=t.data1
SET data=t.data2  //etc...
FROM TempUpdateTable t WHERE t.id IN
  (SELECT d.in FROM TempUpdateTable t JOIN YourData d 
    ON t.id=d.id WHERE d.timestamp=d.timestamp)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文