Postgres SELECT 计数 ... 更新
Postgres SELECT COUNT ... FOR UPDATE
这是我正在尝试做的伪代码:
rate_count = SELECT COUNT(id) FROM job WHERE last_processed_at >= ?
current_limit = rate_limit - rate_count
if current_limit > 0
UPDATE job SET state='processing'
WHERE id IN(
SELECT id FROM job
WHERE state='pending'
LIMIT :current_limit
)
除了并发问题,我可以正常工作。当 运行 同时来自多个会话时,两个会话 SELECT 因此更新相同的东西:(
我可以通过在其 SELECT 子查询中添加 FOR UPDATE 来获得第二个原子查询。但是我无法将 FOR UPDATE 添加到第一个查询中,因为聚合函数不允许 FOR UPDATE
如何让这块成为原子交易?
您可以在子查询中执行 FOR UPDATE:
rate_count := COUNT(id)
FROM (
SELECT id FROM job
WHERE last_processed_at >= ? FOR UPDATE
) a;
您也可以在单个查询中完成所有操作:
UPDATE job SET state='processing'
WHERE id IN (
SELECT id FROM job
WHERE state='pending'
LIMIT (SELECT GREATEST(0, rate_limit - COUNT(id))
FROM (SELECT id FROM job
WHERE last_processed_at >= ? FOR UPDATE) a
)
)
这是我正在尝试做的伪代码:
rate_count = SELECT COUNT(id) FROM job WHERE last_processed_at >= ?
current_limit = rate_limit - rate_count
if current_limit > 0
UPDATE job SET state='processing'
WHERE id IN(
SELECT id FROM job
WHERE state='pending'
LIMIT :current_limit
)
除了并发问题,我可以正常工作。当 运行 同时来自多个会话时,两个会话 SELECT 因此更新相同的东西:(
我可以通过在其 SELECT 子查询中添加 FOR UPDATE 来获得第二个原子查询。但是我无法将 FOR UPDATE 添加到第一个查询中,因为聚合函数不允许 FOR UPDATE
如何让这块成为原子交易?
您可以在子查询中执行 FOR UPDATE:
rate_count := COUNT(id)
FROM (
SELECT id FROM job
WHERE last_processed_at >= ? FOR UPDATE
) a;
您也可以在单个查询中完成所有操作:
UPDATE job SET state='processing'
WHERE id IN (
SELECT id FROM job
WHERE state='pending'
LIMIT (SELECT GREATEST(0, rate_limit - COUNT(id))
FROM (SELECT id FROM job
WHERE last_processed_at >= ? FOR UPDATE) a
)
)