在泛微 E9 里提交流程,弹出”单号已存在””编号重复””该流水号已被使用”——这一般不是网络抖动,而是 E9 的 requestmark(请求编号)生成时撞车了。常见根因就三类:编号规则的”预留编号”踩坑、并发提交撞 businessId 幂等、或者数据恢复后库里已存在该单号。下面四步从配置查到数据库,基本能定位并修复。
第一步:查编号规则的”预留编号”
进 流程引擎 → 路径管理,打开对应流程 → 高级设置 → 流程编号。重点看两项:起始编号 和 预留编号。预留编号是系统预先占用的号段,如果它和当前流水重叠,新提交会直接报”单号重复”。把预留号段清空或调开,再试提交。
路径管理 → 选择流程 → 高级设置 → 流程编号
检查字段:起始编号 / 预留编号 / 编号规则当前值
第二步:并发提交撞了 businessId 幂等
很多二开接口用 businessId 做幂等键。一旦前端在弱网卡或 Nginx 重试下,300ms 内把同一个 businessId 提交了多次,而 E9 的 RequestService.createRequest() 默认没有防重,就会抛 DuplicateKeyException,在用户侧就表现为”单号重复”。修法有两层:接口层对 businessId 加去重(Redis setnx 或数据库唯一索引),前端提交后立刻把按钮置灰,禁止重复点。
第三步:直接查库里有没有这单号
到底库里是不是真有这条单号,一条 SQL 就能确认。如果查出来是迁移/恢复残留的脏数据,按流程归档或修正:
SELECT requestmark, COUNT(*)
FROM workflow_requestbase
WHERE requestmark = 'REQ-2024-0001'
GROUP BY requestmark;
有结果且确实是历史残留,说明编号规则的”当前值”没跟上表里最大单号,跳到第四步调起始值。
第四步:调起始值或重建编号规则
临时解法:把流程编号的起始编号直接调大到”库里最大单号 + 1″,避开冲突段,提交立刻恢复。长期不规范的建议重做编号规则,避免预留号段重叠、避免多个流程共用同一号段。
踩坑实录
一次版本升级后做数据库迁移,恢复脚本把 workflow_requestbase 里几百条老单号也导进去了,可编号规则的”当前值”没同步,新提交流程从 1 开始生成 REQ-2024-0001,立刻和库里已有的撞上,前台报”单号重复”。我一开始以为是 WAF 拦了提交,翻 Security 日志是空的;最后跑了一条 SELECT MAX(requestmark) 才发现库里最大就是 0001。把起始编号改成 0002 后提交恢复。教训很实在:迁移完一定要核对编号当前值和表里最大单号是否一致,不然第一笔提交就卡。
四步对照表
| 排查步骤 | 典型根因 | 动作 |
|---|---|---|
| 第一步 编号规则 | 预留编号与流水重叠 | 清空/错开预留号段 |
| 第二步 并发提交 | businessId 未防重被重试 | 接口去重 + 按钮置灰 |
| 第三步 查库 | 迁移残留脏单号 | SELECT 确认后归档 |
| 第四步 调起始值 | 当前值落后最大单号 | 起始编号改大 |
常见问题
Q:只有某一个流程报重复,其他正常?
基本锁定在该流程的编号规则,先看它的预留编号和当前值,别动全局设置。
Q:报 DuplicateKeyException 但库里查不到这单号?
多半是 businessId 幂等层的问题,不是 requestmark 本身,去查接口重试和唯一索引。
Q:改了起始编号还是重复?
确认有没有多个流程共用同一号段规则,或者预留编号里写死了你刚改的号。
你在 E9 里遇到的单号报错具体是哪一句?欢迎到 fenij.com 留言,把报错文案贴出来,我帮你对着这四步定位。