如何在DB2上通过WHERE条件跨多个表进行安全的“SELECT FOR UPDATE”操作?

11

问题

在一个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查询,而不会引入死锁可能发生的地方?

1个回答

15

首先,如果您需要隔离级别为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进行了一些测试,没有发生死锁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接