Как сделать безопасное «SELECT FOR UPDATE» с условием WHERE для нескольких таблиц в DB2? - PullRequest
11 голосов
/ 07 октября 2010

Задача

В 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 голосов
/ 12 октября 2010

Во-первых, для уровня изоляции READ_COMMITTED вам не нужно указывать WITH RR, потому что это приводит к уровню изоляции SERIALIZABLE. Для указания WITH RS (Read Stability) достаточно.

Чтобы распространить 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

Я провел несколько тестов в DB2 через JDBC, и он работал без тупиков.

...