选择后postgres更新

tbh*_*bh1 24 postgresql select

我想一气呵成:

SELECT * FROM jobs WHERE status='PENDING';
UPDATE jobs SET status='RUNNING' WHERE status='PENDING';
Run Code Online (Sandbox Code Playgroud)

因此,获取所有待处理的作业,然后立即将它们设置为"RUNNING".

我不希望在两个语句中一个接一个地执行此操作的原因是作业可以在SELECT之后但在UPDATE之前作为'PENDING'添加到作业表中,因此我最终将作业设置为RUNNING,即使当它处于PENDING状态时,我没有抓住它.

反正有没有一个人这样做?所以我希望SELECT和UPDATE的结果在运行中发生.

谢谢.

a_h*_*ame 49

为什么不使用RETURNING子句并在一个语句中处理这两个事情:

UPDATE jobs 
    SET status='RUNNING' 
WHERE status='PENDING'
RETURNING *
Run Code Online (Sandbox Code Playgroud)

这样,您将获得UPDATE使用单个原子操作更改的所有行.

  • 如果您返回的不仅仅是一张表,而是与其他表以及来自不同表的列的多个连接怎么办? (2认同)

dcp*_*dcp 17

通常,您应该使用一个UPDATE语句来执行此操作.在UPDATE语句运行时,UPDATE通常不会受到可能已更改的行的影响,但是,此处读取事务隔离级别是很好的.

假设您使用的是Read Committed的默认设置,它的内容如下:

Read Committed是PostgreSQL中的默认隔离级别.当事务在此隔离级别上运行时,SELECT查询仅查看在查询开始之前提交的数据;

关于更新:

UPDATE,DELETE,SELECT FOR UPDATE和SELECT FOR SHARE命令在搜索目标行方面与SELECT的行为相同:它们只能查找从命令开始时间开始提交的目标行.但是,这样的目标行可能已经被另一个并发事务更新(或删除或锁定).在这种情况下,将要更新的服务器将等待第一个更新事务提交或回滚(如果它仍在进行中).如果第一个更新程序回滚,则其效果被否定,第二个更新程序可以继续更新最初找到的行.如果第一个更新程序提交,则第二个更新程序将在第一个更新程序删除它时忽略该行,否则它将尝试将其操作应用于该行的更新版本.重新评估命令的搜索条件(WHERE子句)以查看该行的更新版本是否仍与搜索条件匹配.如果是,则第二更新程序从该行的更新版本开始继续其操作.(在SELECT FOR UPDATE和SELECT FOR SHARE的情况下,这意味着它是被锁定并返回给客户端的行的更新版本.)

所以在你的场景中,一个UPDATE应该没问题.

请记住,有一个所谓的SELECT FOR UPDATE语句,它将锁定您选择的行.你可以在这里阅读.您需要使用此功能的方案将在预订系统中.考虑这个例子:

  1. 执行SELECT以查明XYZ房间是否可用于日期X的预订.
  2. 房间可用.执行UPDATE查询以预订房间.

你看到这里的潜在问题了吗?如果在步骤1和2之间,房间被另一个交易预订,那么当我们到达步骤2时,我们的假设不再有效,即房间可用.

但是,如果在步骤1中我们使用SELECT FOR UPDATE语句,我们确保没有其他事务可以锁定该行,所以当我们去更新行时,我们知道这样做是安全的.

但同样,在您的场景中,不需要此SELECT FOR UPDATE,因为您在一个语句中执行所有操作并且未提前检查任何内容.


Clo*_*eto 5

begin;
select * 
from jobs 
where status='pending'
for update
;
update jobs 
set status='running' 
where status='pending';
commit;
Run Code Online (Sandbox Code Playgroud)