嵌套的 SQL 查询是原子的吗?

Are nested SQL queries atomic?

我有一些微服务(几乎)系统,其中每个程序都有自己的端口。此外,并非系统中的所有端口都可用。为简单起见,我决定在 PostgreSQL 中的 table 中保留一个空闲端口列表。因此,我有这个 table:

service | port
-------------------
sm_srv  | 5600
null    | 5601
...

分别如果service栏中的值为null,则端口空闲,否则为忙。 然而,如果你先 select 所有空闲端口,然后占用其中一个,那么操作就变成了非原子操作,这是合乎逻辑的。这可能会导致两个服务试图占用同一个端口的情况。

我正在尝试使此操作成为原子操作。为此,我决定不做 select,而是立即更新。但是,在这里我面临 SQL 知识匮乏的问题,并且在 Internet 上找不到关于该主题的任何内容。我的最终要求:

UPDATE table 
  SET service='asd' 
WHERE port IN (SELECT port FROM table WHERE service IS NULL LIMIT 1)
RETURNING port;

提问:这样的操作是原子的吗?或者也许我可以通过某种方式使我需要的东西变得更容易?

您应该编写子查询,以便它锁定找到的行以防止并发修改:

UPDATE services                                      
   SET service='asd'
WHERE port IN (SELECT port
               FROM services
               WHERE service IS NULL
               FOR NO KEY UPDATE SKIP LOCKED
               LIMIT 1)
RETURNING port;

SKIP LOCKED 导致查询忽略锁定的行而不是等待锁定。