Вы должны «заблокировать» строку, которую собираетесь обработать. Такая «блокировка» должна выполняться одновременно с минимальным количеством конфликтов / ошибок.
Один из способов заключается в следующем:
Create table change
(
id int not null generated always as identity
, v varchar(10)
) in userspace1;
insert into change (v) values '1', '2', '3';
Create table change_process_rel
(
id int not null
, pid int not null
, status int not null
) in userspace1;
create unique index change_process_rel1 on change_process_rel(id);
Теперь вы должны иметь возможность запускать один и тот же оператор из нескольких одновременных сеансов:
SELECT ID
FROM NEW TABLE
(
insert into change_process_rel (id, pid, status)
select c.id, mon_get_application_handle(), 1
from change c
where not exists (select 1 from change_process_rel r where r.id = c.id)
fetch first 1 row only
with ur
);
Каждый такой оператор вставляет 1 или 0 строк в таблицу change_process_rel
, которая используется здесь как таблица «блокировки». Возвращается соответствующий ID
из change
, и вы можете продолжить обработку соответствующего события в той же транзакции.
Если транзакция завершается успешно, строка, вставленная в таблицу change_process_rel
, сохраняется, поэтому соответствующий id
из change
может рассматриваться как обработанный. Если транзакция завершается неудачно, соответствующая строка «lock» из change_process_rel
исчезает, и эта строка может быть позже обработана этим или другим приложением.
Проблема этого метода в том, что, когда обе таблицы становятся достаточно большими, такой суб-выбор может работать не так быстро, как раньше.
Требуется разместить столбец status
в таблицу change
. К сожалению, Db2 для LUW не имеет функциональности SKIP LOCKED
, что может помочь с алгоритмами такого рода.
Если, скажем, status=0
"не обработан", а status<>0
- некоторая обработка / обработка состояние, затем после установки этих переменных реестра DB2_EVALUNCOMMITTED
и DB2_SKIP*
и перезапуска экземпляра вы можете «перехватить» следующую ID
для обработки с помощью следующего оператора.
SELECT ID
FROM NEW TABLE
(
update
(
select id, status
from change
where status=0
fetch first 1 row only
)
set status=1
);
Как только вы его получите , вы можете выполнить дальнейшую обработку этого ID
в той же транзакции, что и ранее.
Хорошо создать индекс производительности: создать индекс change1 on change (status); и может установить эту таблицу как изменчивую или собирать статистику распределения по этому столбцу в дополнение к регулярной статистике по таблице и ее индексам периодически.
Обратите внимание, что такая настройка переменных реестра имеет глобальный эффект, и вам следует помнить об этом .. .