如何在DB2上的多个表上使用WHERE条件执行安全的"SELECT FOR UPDATE"?

tan*_*ens 11 db2 database-deadlocks

问题

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

SELECT o.Id FROM Table1 o, Table2 x WHERE [...] FOR UPDATE WITH RR
Run Code Online (Sandbox Code Playgroud)

给我错误消息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
Run Code Online (Sandbox Code Playgroud)

一切正常.

新问题

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

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

小智 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
Run Code Online (Sandbox Code Playgroud)

我通过JDBC对DB2进行了一些测试,它没有死锁.