嵌套的 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
导致查询忽略锁定的行而不是等待锁定。
我有一些微服务(几乎)系统,其中每个程序都有自己的端口。此外,并非系统中的所有端口都可用。为简单起见,我决定在 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
导致查询忽略锁定的行而不是等待锁定。