Ab Initio中如何实现next_in_sequence()跨执行接续递增不重置
问题根因
你遇到的序列每次作业重启就从头计数的问题,核心是当前调用的序列没有持久化保存全局递增的游标状态,常见诱因有三个:
- 每次作业执行前都重复执行序列创建语句,直接把序列初始值重置回1
- 使用的是会话级/作业进程内的临时内存序列,作业进程退出后序列游标直接被销毁,下次启动自然从初始值开始计数
- 序列配置了循环属性,或者作业逻辑里绑定了每次启动重置序列的规则
可行解决方案
根据你的作业运行环境二选一即可:
方案1:持久化数据库序列(生产环境优先选,稳定性最高)
不要在作业逻辑里动态创建序列,提前在数据库中创建全局持久化的序列对象,不要配置任何自动重置逻辑,所有作业运行统一调用这一个序列取号:
- 提前创建持久化序列,初始值设为1,步长设为1,关闭循环属性,不要配置作业退出自动删除规则
-- 以PostgreSQL语法为例,MySQL、Oracle等其他数据库仅需微调序列创建语法 CREATE SEQUENCE folio_seq START WITH 1 INCREMENT BY 1 NO CYCLE; - 作业内生成
folio字段值时,直接拼接序列返回值即可,不需要在作业启动阶段做序列初始化:
这类持久化序列的当前游标值会存在数据库系统表中永久维护,不管作业重启多少次、隔多久跑一次,每次调用取号函数都会从上一次最后生成的值往后顺延,完全满足接续生成的要求。'seq-' || nextval('folio_seq') AS folio避坑:不要在作业开头加类似
ALTER SEQUENCE folio_seq RESTART WITH 1的重置语句,否则会回到从头计数的问题。
方案2:外部存储维护序列游标(适合无数据库依赖的轻量作业)
如果作业场景没法使用数据库持久化序列,找一个不会随作业进程退出销毁的持久化存储介质,存上一次生成的最后一个序列的数字后缀,每次作业启动先读取这个基准值,再基于该值往后生成序号:
- 存储介质可以选本地持久化配置文件、作业共用的缓存、分布式存储等,本地文件存储的实现逻辑参考如下伪代码:
只要存储的记录文件不被手动删除或篡改,不管作业执行多少次,都会顺着上一次的最后一个值持续递增。import os # 作业启动第一步:读取上次持久化存储的最后一个序列值 seq_store_path = "./last_folio_seq_record" if os.path.exists(seq_store_path): with open(seq_store_path, 'r', encoding='utf-8') as f: current_num = int(f.read().strip()) else: current_num = 0 # 作业处理阶段:逐行生成folio字段 for single_record in job_wait_process_list: current_num += 1 single_record['folio'] = f"seq-{current_num}" # 作业结束前:把最新的序列值写回持久化存储 with open(seq_store_path, 'w', encoding='utf-8') as f: f.write(str(current_num))
注意事项
- 不要用作业进程内的局部内存变量存储序列值,作业进程退出后内存数据会被清空,下次启动必然从头计数
- 如果是分布式多实例并行跑作业,一定要选所有实例都能访问的公共存储(比如数据库序列、全局公共缓存)维护序列游标,避免多实例各自计数出现重复值。
内容的提问来源于stack exchange,提问作者KLM
相关产品推荐
相关产品推荐

