当前位置:首页 > 文章列表 > 数据库 > 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 BYLIMIT,并检查 (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推荐
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    161次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    88次使用
  • ClickPrompt:AI提示词生成与优化工具,支持Stable Diffusion、ChatGPT及代码辅助
    ClickPrompt
    ClickPrompt是一款专为AI提示词编写者设计的开源在线工具,支持Stable Diffusion绘图、ChatGPT对话及GitHub Copilot代码辅助。提供Prompt自动生成、一键运行、社区分享及可视化优化功能,帮助用户高效获取精准AI输出。
    48次使用
  • PromptHero官网:AI提示词搜索、优化与学习平台,支持Midjourney/Stable Diffusion
    PromptHero
    PromptHero是专业的AI提示词搜索引擎与优化平台,支持Stable Diffusion、Midjourney等主流模型。提供海量提示词库、分类搜索、在线课程及社区互动,助力用户高效生成高质量AI图像与文本。
    30次使用
  • OpenArt免费开源指南:Stable Diffusion Prompt Book提示词手册详解
    Stable Diffusion Prompt Book
    深入解析OpenArt推出的Stable Diffusion Prompt Book,这本免费的开源提示词指南涵盖从基础语法到高级技巧,提供风格化词库与参数建议,助您优化AI绘画生成效果。
    33次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码