ITPub博客

首页 > 数据库 > MySQL > MES报工接口幂等怎么做?唯一键、去重表与重试策略

MES报工接口幂等怎么做?唯一键、去重表与重试策略

原创 MySQL 作者:制造业数字化观察 时间:2026-11-03 10:20:49 0 删除 编辑

MES 报工是车间最频繁的写入之一:扫码枪、工位终端、AGV 或 PDA 在工序完成时把完工数量、合格/不合格数、工时、设备/模具/批次等信息推给 MES。网络抖动、WIFI 漫游、扫码枪丢包、终端重启都会导致同一笔报工被重发。如果接口不是幂等的,重复提交会产生重复报工记录,产量虚高、在制品不准、追溯链条断裂,后续对账和成本核算都要手工清洗。

幂等的含义在这里很具体:同一个报工请求无论提交几次,MES 最终只记录一次有效的完工数据。实现幂等通常不靠"前端只发一次"--前端不可控,必须落到接口与数据库层面。常见做法是围绕唯一键、去重表和重试策略组合,但每一种都有自己的适用边界和落地成本。

唯一键是最直接的第一道防线。报工接口的幂等关键是把"哪一笔报工"定义清楚:工单号 + 工序号 + 工位/设备 + 报工批次/扫码序列 + 操作人/班次 通常能唯一标识一次报工。把这些字段拼成复合唯一键(例如在 work_order_report 表上加 UNIQUE INDEX uk_report(wo_no, op_seq, station_id, scan_batch, operator, shift_code)),重复提交直接命中唯一约束,数据库返回 Duplicate entry,接口层捕获该错误返回"已报工"即可。很多项目会再加一个幂等流水号 idempotent_key(由调用方生成、在请求体和 URL 参数里都带),用 (idempotent_key) 做单列唯一键,这样不管报工字段怎么组合,幂等语义完全由一个字段承担,接口层逻辑更干净。唯一键方案的局限在于:它只能区分"完全相同"的请求,如果调用方每次生成的扫描批次/数量/时间戳不同,唯一键就拦不住重复;此外,唯一键冲突是硬拦截,不会自动更新业务字段,如果业务允许"以最新为准"补数量,唯一键本身做不到。


去重表(幂等日志表)是唯一键的常用搭档,也是处理"相似但不完全相同"重复的核心手段。做法是在写报工业务表之前,先往 idempotent_log 写一行:幂等键、请求摘要(报工数量、合格数、请求时间等)、结果状态和报工主表 ID。去重表的幂等键建唯一索引,插入时如果幂等键已存在,就说明之前已经处理过这请求——接口可以返回之前处理的结果,直接对调用方呈现幂等效果。去重表有两个常见变体值得比较:第一种是插入式去重,正常路径 INSERT 幂等日志,重复路径捕获唯一冲突后 SELECT 已有记录并返回;第二种是 INSERT ... ON DUPLICATE KEY UPDATE,在冲突时用 UPDATE 把 result 列翻到 DONE,同时保留最初的业务结果。前者更轻量、不需要额外 UPDATE,但在高并发下"插入冲突 → SELECT"可能遇到锁竞争;后者一次往返完成,但 ON DUPLICATE KEY UPDATE 在高写入表上会带来行锁升级为间隙锁的风险,MySQL 8.0 的锁优化改善了这种情况,仍需在压测中确认。去重表也带来存储与生命周期问题:报工量大的工厂每天几十万到上百万条请求,幂等日志如果不归档,几个月就会膨胀。常见做法是幂等日志只保留最近 N 天(例如 7-30 天,覆盖重试窗口和客诉排查期),过期数据批量移入历史库或按天分区后直接 DROP PARTITION。

重试策略决定了重复到底会不会发生,以及发生的窗口有多大。接口幂等只能兜底,真正减少重复靠的是调用方的重试治理。车间场景里,重试最常见的原因是网络瞬断和 MES 侧事务提交慢。如果调用方用"失败立即重发 + 固定间隔重发 N 次",在 MES 处理较慢但尚未返回时,同一请求会并发飞行多份,即使接口幂等,也会在短时间内产生多次唯一键冲突,拖慢接口。更稳的做法是调用方使用递增退避(例如 1s、3s、8s)并设置总超时,配合报工请求里携带单调递增的 seq 或单调时间戳 + idempotent_key,MES 侧在去重表里对同一幂等键允许一个"处理中 → 已处理"的状态机:初次请求插入 IN_PROGRESS,后续重复在窗口期内直接返回等待或返回已有结果。这样在重试窗口内,重复被压缩到去重表的轻量查询,而不是落到业务表的写路径。需要正面说明的是:如果调用方每次失败后修改了报工数量或重新生成了幂等键,这就不再是"重试"而是新报工,幂等机制不应拦截,否则会把合法的补报/修正当成重复吞掉。

把三者串起来,典型的落地清单是:第一,调用方统一生成 idempotent_key(例如基于工单+工序+扫码时间窗口+随机盐的哈希,或由调用方网关分配单调流水号),放在报工请求的请求体和 Header 中,重试时 idempotent_key 不变。第二,MES 接口层收到请求后,先查/写去重表(INSERT ... ON DUPLICATE KEY UPDATE 或插入+冲突回查),重复则直接返回上次结果,不进入业务逻辑。第三,报工业务表用 (wo_no, op_seq, station_id, scan_batch, ...) 复合唯一键兜底,去重表异常写失败时的最后一道拦截。第四,调用方重试使用递增退避+总超时,禁止"失败即重发且修改数量"的隐式重复。第五,去重表保留 7-30 天,按期归档,监控唯一键冲突率与去重命中率,冲突率持续偏高说明调用方重试策略需要治理而不是继续在接口侧加拦截。FAQ 补充三个高频问题:扫码枪重复扫码算不算重复报工?不算,重复扫码是业务上的多件报工,应通过扫码去重或按件累加在业务层解决,接口幂等只处理同一笔报工请求的重发。MES 侧能否用 Redis SETNX 做幂等?可以,但 Redis 只是缓存层,断电或主从切换会丢幂等状态,生产建议以数据库去重表为权威、Redis 仅用于降低数据库压力的加速层。报工回滚(取消报工)要不要幂等?要,取消报工同样可能重发,取消操作应有独立的幂等键或复用原报工的 idempotent_key 并在去重表里记录 CANCEL 状态。本文部分内容在撰写过程中使用了 AI 辅助,技术判断与参数示例由作者校验后发布。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70051529/viewspace-3187412/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
关注离散制造MES、WMS、条码追溯与设备数据采集的实施经验分享。

注册时间:2026-10-24

  • 博文量
    7
  • 访问量
    4262