避免页签系列问题的文档命名

当您在 ERPNext 中保存文档(如销售发票、库存录入、付款单等任何带有自动生成编号的内容)时,系统需要确定序列中的下一个编号(例如 0001、0002、0003 等)。

为了确保两个文档永远不会获得相同的编号,ERPNext 在名为 tabSeries 的表中为每个命名系列维护一个计数器。在分配下一个编号之前,它会锁定该计数器,防止其他操作同时访问,然后加 1,最后解锁。这个过程在瞬间完成,因此通常您不会察觉到。

如果同时创建数百个文档,并且它们都使用相同的命名系列,那么它们都需要同一个计数器。同一时间只能有一个操作持有锁,因此其他操作必须排队等待。

当排队等待的时间变长时,您可能会遇到以下情况:

  • 文档保存耗时较长
  • 批量导入或批量提交速度缓慢甚至卡住
  • 出现类似“Record has changed since last read in table ‘tabSeries’”的错误,或数据库锁/死锁超时
  • 后台任务在队列中堆积

在业务高峰期、月末或为应对负载而增加更多工作进程后,这个问题会变得更加严重,因为现在有更多的交易在争抢同一个计数器。

为什么定制化会加剧此问题

一个非常常见的原因是定制化配置强制大量交易使用单一、受限的命名系列。所有交易都汇聚到一个计数器上,导致该计数器成为整个操作的瓶颈。规模越大,这个单一计数器后面的排队就越长。

简单的解决方法:使用多个命名系列

计数器是按命名系列分别锁定的。因此解决方法很简单:

为不同的交易组分配各自的命名系列,这样它们就会使用不同的计数器,不再相互等待。

与其在一个计数器前排长队,不如开设多个计数器。每个队列独立并行运行。

拆分系列的好方法

选择任何能自然区分您交易的方式。例如:

按以下方式拆分 示例系列
分支机构 SINV-MUM-.YYYY.-.####, SINV-DEL-.YYYY.-.####
项目 SINV-PROJ-A-.####, SINV-PROJ-B-.####
成本中心 SINV-CC01-.####, SINV-CC02-.####
部门 SINV-SALES-.####, SINV-SUPPORT-.####

每种情况的核心思想都是一样的:同时运行的交易不应都挤在同一个计数器上。您将它们分散得越开,每个交易需要等待的时间就越短。

针对超大规模操作的额外建议

如果您经常一次性创建大量文档:

  • 将大批量导入分散到多个系列中,以分担负载,而不是将所有内容都导入到一个系列下。
  • 在导入/API 调用时尽可能自行提供名称。如果文档已有名称,ERPNext 将完全跳过计数器。无需锁定,无需等待。例如,客户 ID 是根据客户名称本身生成的。
  • 避免将所有内容强制归入一个狭窄系列的定制化配置。审查任何自定义命名逻辑,确保它不会将所有交易都汇聚到单个计数器上。
  • 如果流程允许,稍微错开超大型任务的启动时间,而不是在同一瞬间全部触发。