如何进行安全的“选择更新”在 DB2 上的多个表上使用 WHERE 条件?

发布于 2024-09-26 15:49:57 字数 657 浏览 4 评论 0原文

问题

在 DB2(版本 9.5)上,SQL 语句

SELECT o.Id FROM Table1 o, Table2 x WHERE [...] FOR UPDATE WITH RR

给出错误消息 SQLSTATE=42829 (不允许使用 FOR UPDATE 子句,因为无法修改游标指定的表)。

我需要指定 WITH RR的附加信息

,因为我正在隔离级别 READ_COMMITTED 上运行,但我需要在另一个进程运行同一查询时阻止我的查询。

到目前为止的解决方案...

如果我像这样查询:

SELECT t.Id FROM Table t WHERE t.Id IN (
    SELECT o.Id FROM Table1 o, Table2 x WHERE [...]
) FOR UPDATE WITH RR

一切正常。

新问题

但是现在当多个进程同时执行此查询时,我偶尔会遇到死锁异常。

问题

有没有一种方法可以在不引入可能发生死锁的地方的情况下制定 FOR UPDATE 查询?

Problem

On a DB2 (version 9.5) the SQL statement

SELECT o.Id FROM Table1 o, Table2 x WHERE [...] FOR UPDATE WITH RR

gives me the error message SQLSTATE=42829 (The FOR UPDATE clause is not allowed because the table specified by the cursor cannot be modified).

Additional info

I need to specify WITH RR, because I'm running on isolation level READ_COMMITTED, but I need my query to block while there is another process running the same query.

Solution so far...

If I instead query like this:

SELECT t.Id FROM Table t WHERE t.Id IN (
    SELECT o.Id FROM Table1 o, Table2 x WHERE [...]
) FOR UPDATE WITH RR

everything works fine.

New problem

But now I occasionally get deadlock exceptions when multiple processes perform this query simultaneously.

Question

Is there a way to formulate the FOR UPDATE query without introducing a place where a deadlock can occur?

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

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

发布评论

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

评论(1

魔法唧唧 2024-10-03 15:49:57

首先,对于隔离级别 READ_COMMITTED,您不需要指定 WITH RR,因为这会导致隔离级别 SERIALIZABLE。指定WITH RS(读取稳定性)就足够了。

要将FOR UPDATE WITH RS传播到内部选择,您必须另外指定USE AND KEEP UPDATE LOCKS

因此,完整的语句如下所示:

SELECT t.Id FROM Table t WHERE t.Id IN (
    SELECT o.Id FROM Table1 o, Table2 x WHERE [...]
) FOR UPDATE WITH RS USE AND KEEP UPDATE LOCKS

我通过 JDBC 在 DB2 上进行了一些测试,它的工作没有死锁。

First, for having isolation level READ_COMMITTED you do not need to specify WITH RR, because this results in the isolation level SERIALIZABLE. To specify WITH RS (Read Stability) is enough.

To propagate the FOR UPDATE WITH RS to the inner select you have to specify additionally USE AND KEEP UPDATE LOCKS.

So the complete statement looks like this:

SELECT t.Id FROM Table t WHERE t.Id IN (
    SELECT o.Id FROM Table1 o, Table2 x WHERE [...]
) FOR UPDATE WITH RS USE AND KEEP UPDATE LOCKS

I made some tests on a DB2 via JDBC and it worked without deadlocks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文