postgresql - 并发查询给出意外数据
问题描述
我执行几个进程以连续(更新+选择)来自 postgresql 的数据(启用自动提交选项),并通过执行其他进程完成的先前更新来获取应该已经被过滤掉的数据。
这本质上是一个队列,所有行最初的状态=0,并以某种复杂(未显示)的顺序逐行选择。每个待处理的行都设置为 status=1,pid=(process id) 和 uniqueid=(some iterating id),但不同的进程出于某种原因共享相同的行。
过度简化(但仍无法正常工作)的示例如下:
表定义:
create table Todq (
id bigserial primary key,
url varchar(1024),
status integer not null,
pid integer,uniqueid bigint,
priority integer
);
create index Iodq1 on Todq (status,priority,id);
create index Iodq2 on Todq (pid,uniqueid);
更新(获取队列中的下一个元素,设置进程 pid 并迭代 uniqueid):
update Todq odq2
set status=1,pid=?,uniqueid=?
from (
select odq.id
from Todq odq
where odq.status=0
order by odq.priority desc,odq.id
limit 1
) odq1
where odq2.id=odq1.id
选择(按进程 ID 和可递增的唯一 ID 选择):
select odq.id,odq.url,odq.pid,odq.uniqueid
from Todq odq
where odq.status=1 and pid=? and uniqueid=?
我在 perl 中创建了一个测试台,它将选择的值写入 logs/$$.log,因此不同的日志共享相同的条目(尽管具有不同的 pid 和 uniqueid)。
解决方案
答案是使用(选择 .. 进行更新),例如:
update Todq odq2
set status=1,pid=?,uniqueid=?
from (
select odq.id
from Todq odq
where odq.status=0
order by odq.priority desc,odq.id
limit 1
for update
) odq1
where odq2.id=odq1.id
推荐阅读
- jpa - JPA 继承:查询因未知列而失败
- html - 我链接了 boostrap.css 和 boostrap.min.css 但样式不起作用
- django - Django Admin,使用完全相同的外键限制多对多选择
- android - 如何在 ktlint 中禁用文件名?
- javascript - 如何动态调用componentDidMount中的函数?
- python - 调用路由时,Flask 正在从不同的路径加载静态文件
- javascript - 在终端中使用 wkhtmltopdf 测试时 Javascript 不起作用
- c - 是否可以使用预处理器指令验证表达式?像 #if (a == b)
- angular - 如何测试对输入字段中的 keydown 事件作出反应的指令
- javascript - 如何使用 JavaScript 代码查找 WeekOff