You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并发环境下如何按组选取首行且避免进程重复获取?

解决并发进程分组获取唯一首行的行锁问题

你的问题出在锁的时机太晚:CTE子句groups会先无锁查询全表并计算行号,多个并发进程此时会得到完全相同的rn=1的行集合,后续再对结果加锁时,已经有多个进程拿到了同一行的引用,导致重复获取。

正确的SQL查询(PostgreSQL环境)

利用PostgreSQL的DISTINCT ON特性直接获取分组首行,同时在查询阶段就加锁:

SELECT DISTINCT ON (a, b) *
FROM tests
ORDER BY a, b, id ASC
FOR UPDATE SKIP LOCKED
LIMIT 1;

原理说明

  1. DISTINCT ON (a, b)会严格按照a、b分组,返回每组中id最小的首行(由ORDER BY a, b, id ASC保证)
  2. FOR UPDATE SKIP LOCKED会在查询过程中直接锁定选中的行,其他并发进程执行同一查询时,会自动跳过已被锁定的分组行,转而获取未被锁定的下一个分组首行
  3. LIMIT 1保证每个进程每次只获取一个分组的首行,符合业务需求

跨数据库兼容写法

如果你的数据库不支持DISTINCT ON,可改用提前锁定分组最小id的写法:

WITH locked_groups AS (
    SELECT *
    FROM tests
    WHERE id IN (
        SELECT MIN(id)
        FROM tests
        GROUP BY a, b
    )
    FOR UPDATE SKIP LOCKED
    LIMIT 1
)
SELECT * FROM locked_groups;

关键注意事项

  • 必须在事务上下文中执行该查询,处理完计算任务后及时提交事务,释放锁,让其他进程能获取剩余分组

内容的提问来源于stack exchange,提问作者str.gsub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:17:20