当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 多个消费者怎么用 SKIP LOCKED 领取任务

MySQL 多个消费者怎么用 SKIP LOCKED 领取任务

来源:17golang原创 2026-09-06 08:38:43 0浏览 收藏

多个消费者共同读取 MySQL 任务表时,核心写法是把领取动作放进短事务:先用 SELECT ... FOR UPDATE SKIP LOCKED 锁定一条待处理任务,再在同一事务里把它改成 processing,最后提交。其他消费者遇到这条已锁记录会直接跳过,继续尝试下一条,而不是排队等待。

要点速览
  • SKIP LOCKED 适合队列式表,不适合要求完整一致视图的普通查询。
  • 领取和状态更新必须在同一个 InnoDB 事务中,提交后再执行耗时业务。
  • 没有任务、消费者崩溃、复制模式和长任务超时,都要有明确的恢复策略。

先把任务表设计成可并发领取

先准备一个状态清晰、能快速筛选的队列表。下面的字段足够演示领取路径,生产环境还可以增加重试次数、租约截止时间和错误摘要。

CREATE TABLE task_queue (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    payload JSON NOT NULL,
    status ENUM('pending', 'processing', 'done', 'failed') NOT NULL DEFAULT 'pending',
    claimed_by VARCHAR(64) NULL,
    claimed_at DATETIME NULL,
    PRIMARY KEY (id),
    KEY idx_queue_status_id (status, id) -- 让领取条件和排序共享索引
) ENGINE = InnoDB;

status, id 联合索引对应 WHERE status = 'pending' ORDER BY id。它不是为了保证绝对公平,而是让消费者有稳定的扫描顺序;被锁住的旧任务会被跳过,后面的任务可以先被领取。

字段或条件作用领取时的判断
status表达任务生命周期只选择 pending
id稳定排序和唯一定位领取后用主键更新
claimed_by记录消费者身份便于审计与排障
claimed_at记录租约或超时起点恢复卡住任务时使用
MySQL SKIP LOCKED 任务队列中的任务表字段、状态索引与消费者连接关系
图1:任务状态、联合索引和多个消费者连接共同构成可并发领取的队列表结构。

在短事务里用 FOR UPDATE SKIP LOCKED 抢一条

每个消费者都要使用自己的数据库连接,并显式开启事务。锁定读只有在事务未提交时才有意义;如果开启自动提交,锁可能在语句结束时就释放,领取和标记就无法形成一个原子动作。

START TRANSACTION;

-- 只找待处理且当前没有被其他消费者锁住的任务
SELECT id, payload
  FROM task_queue
 WHERE status = 'pending'
 ORDER BY id
 LIMIT 1
 FOR UPDATE SKIP LOCKED;

-- 应用拿到 id 后,在同一事务内完成状态转移
UPDATE task_queue
   SET status = 'processing',
       claimed_by = 'worker-a',
       claimed_at = NOW()
 WHERE id = 12345
   AND status = 'pending'; -- 防止状态已经变化时误更新

COMMIT; -- 提交后才释放领取锁

应用层要检查查询是否返回了行,以及 UPDATE 的影响行数。查询没有结果时说明当前没有可领取任务,可以短暂退避后重试;不要把它当成异常死循环。两个消费者同时执行时,已被第一个事务锁住的记录会从第二个结果集中消失,但第二个消费者仍可能读到更靠后的任务。

MySQL 官方说明了这个语义:SKIP LOCKED 不等待行锁,直接从结果集中移除被锁行;因此返回的是不一致视图,只适合队列一类允许跳过锁行的场景。它只对行级锁生效,使用语句复制时还要单独评估安全性。

把数据库领取和业务执行分开

不要在事务里调用远程 API、生成文件或执行几分钟的业务。正确边界是“短事务只负责认领,提交后再处理”:任务进入 processing 后,消费者可以在事务外完成工作,成功后更新为 done,失败则写入 failed 或增加重试次数。

进程在提交前崩溃,事务回滚,任务仍是 pending;进程在提交后、业务完成前崩溃,任务可能停留在 processing。后一种情况不能依赖锁自动解决,应结合 claimed_at 做租约超时恢复,并让业务操作具备幂等性。否则恢复消费者可能再次执行已经完成一半的外部动作。

MySQL 领取事务与事务外业务执行的边界,以及 processing、done、failed 状态关系
图2:短事务只覆盖锁定和状态转移,耗时处理位于事务外,并通过状态与租约支持恢复。

上线前检查这几项并发边界

  • 确认表使用 InnoDB,查询条件包含明确的 ORDER BY 和 LIMIT,并检查 (status, id) 索引。
  • 确认每次领取都显式提交或回滚;连接归还连接池前不能留下未结束事务。
  • 为空队列设置退避,死锁或瞬时连接错误采用有限次数重试。
  • 为 processing 任务保存领取者和时间,定时恢复超时租约。
  • 把外部副作用设计成幂等,并根据部署环境评估复制方式和锁等待监控。

常见问题

SKIP LOCKED 会保证任务严格按 id 顺序处理吗?

不会。它只提供“遇到已锁行就跳过”的并发行为,后面的任务可能先完成。需要严格顺序时,应改用单消费者、分区队列或业务层排序。

查询不到任务时应该回滚吗?

如果已经开启事务,建议回滚或提交后再退避,确保连接没有留下未结束事务。空结果本身不是数据库错误。

为什么任务状态已经是 processing,却仍然重复执行?

通常是消费者在提交领取后崩溃,恢复逻辑又重新拿走了超时任务。需要租约、尝试次数和幂等键一起控制,而不是只依赖状态字段。

可以用普通 SELECT 再 UPDATE 代替吗?

不建议。普通读取和更新之间存在竞争窗口,多个消费者可能读到同一行;要么使用锁定读,要么采用带条件的原子更新并设计清晰的重试结果。

因此,MySQL 多消费者队列的最小可靠组合是:InnoDB、短事务、FOR UPDATE SKIP LOCKED、同事务状态更新,以及事务外的幂等执行和超时恢复。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
BATOTO漫画要注册吗?免费模式、广告与隐私边界说明BATOTO漫画要注册吗?免费模式、广告与隐私边界说明
上一篇
BATOTO漫画要注册吗?免费模式、广告与隐私边界说明
Go 为什么不能直接修改 map 里结构体的字段
下一篇
Go 为什么不能直接修改 map 里结构体的字段
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    581次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    620次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    651次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    616次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    432次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码