防止两个线程选择同一行 ibm db2



我遇到的情况是,我有多个(可能是数百个(线程重复相同的任务(如果您好奇,请使用java调度执行器(。此任务需要选择尚未处理的更改行(从名为 change 的表中((处理的更改在名为 process_change_rel 的 m:n join 表中跟踪,该表跟踪进程 ID、记录 ID 和状态(,然后更新回状态。

我的问题是,如何防止来自同一进程的两个线程选择同一行的最佳方法?以下解决方案(用于更新以锁定行(是否有效? 如果没有,请提出可行的解决方案

Create table change(
—id , autogenerated pk 
—other fields
)
Create table change_process_rel(
—change id (pk of change table)
—process id (pk of process table)
—status)

下面列出了我将使用的查询

Select * from 
change c
where c.id not in(select changeid from change_process_rel with cs) for update

请让我知道这是否有效

您必须"锁定"要以某种方式处理的行。当然,这种"锁定"应该同时进行,并尽量减少冲突/错误.
一种方法如下:

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
);

每个这样的语句都会在change_process_rel表中插入 1 或 0 行,此处用作"锁定"表。返回来自change的相应ID,您可以继续处理同一事务中的相应事件.
如果事务成功完成,则插入change_process_rel表中的行将被保存,因此,来自change的相应id可能被视为已处理。如果事务失败,change_process_rel中相应的"锁定"行将消失,此行稍后可能会由此应用程序或其他应用程序处理。
此方法的问题是,当两个表都变得足够大时,这样的子选择可能不会像以前那样快速工作。

另一种方法是使用通过锁定延迟评估未提交的数据。

它需要将status列放入change表中。 不幸的是,Db2 for LUW 没有SKIP LOCKED功能,这可能有助于这种算法.
假设status=0"未处理",并且status<>0是某些正在处理/已处理的状态,那么在设置这些DB2_EVALUNCOMMITTEDDB2_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进行进一步处理.
最好创建一个性能索引: 在更改(状态(时创建索引更改1; 并且可以将此表设置为易失性,或者除了定期收集表及其索引的常规统计信息外,还收集此列的分布统计信息。
请注意,此类注册表变量设置具有全局影响,您应该记住它...

相关内容

  • 没有找到相关文章

最新更新