java - 当有多个进程并行运行时,只消耗表中的一条记录进行处理
问题描述
假设我有一个批处理表,它存储批处理记录列表。java进程需要从表中选择一条记录(最旧的)进行处理。类似的java进程会在不同的机器上并行运行
用例:第二个流程不应选择与第一个流程相同的记录。
create table batch
(
id number primary key,
worker varchar2(32),
status varchar2(32),
created date
);
insert into batch values(1, null, null, sysdate);
insert into batch values(2, null, null, sysdate+6);
我正在考虑以下问题
- 发出更新命令以使用谓词更新批处理表上的一行 - 状态为空,工作人员为空。
- 如果更新计数 > 0,则从表中获取一条记录,其中 worker = 'current worker' 并且状态正在进行中
update batch set worker = 'worker1', status = 'IN_PROGRESS' where
id = (
select id from (
select id from batch
where status is null and worker is null order by created desc
) where rownum = 1
) and status is null and worker is null;
select * from batch where worker = 'worker1' and status = 'IN_PROGRESS'
在这种情况下,当多个java进程发出更新命令时,
- 更新语句会是原子的,它会按预期工作吗?
- 除了如果工人死亡可能无法处理记录这一事实之外,这种方法是否会有任何问题。
解决方案
每个 Java 程序都需要锁定它已获取的记录,并且还需要跳过任何已被另一个程序锁定的记录。这可以通过 SKIP LOCKED 子句来实现。
因此,您的 Java 程序会打开一个光标,如下所示:
SELECT *
FROM t
FOR UPDATE SKIP LOCKED;
当您获取时,如果您遇到未锁定的行,您将“获取”并锁定它。如果您点击了已经被另一个会话获取(并因此锁定)的行,那么它将不会返回给这个调用程序。
推荐阅读
- android - 在带有底部导航栏的片段中折叠工具栏 | 安卓工作室
- python - 对卷积特征和低维输出空间使用嵌入
- rust - 如何从 build.rs 文件中调用我的库中的函数?
- python - 使用 scipy.integrate.nquad 的双积分解决方案与 Integrated.dblquad 不匹配
- php - 如何在xml中转换字符串并循环节点?
- java - NetBeans 平台:如何以编程方式设置基于 Swing 的 GUI 组件的样式?
- android - 从 Android 中的 HTTP 服务器获取公钥
- javascript - 何时何地使用带有异步函数的 catch
- include - 在单行代码中包含多个文件的 Julia 语法
- python - 提取列表元素的数据类型