You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server 2016序列生成ID出现80-100跳号的排查与复现咨询

SQL Server 2016 Sequence 80-100跳号问题:原因与复现方法

一、跳号核心原因

当前调用存储过程时固定@increment=1,走直接执行NEXT VALUE FOR [序列名]的逻辑,跳号的主要诱因是SQL Server Sequence的缓存机制:

  • Sequence默认启用缓存(默认缓存大小为50),若创建序列时显式指定更大的缓存值(比如CACHE 100),实例会一次性预加载一批序列值到内存,供后续请求快速获取。
  • 当SQL Server服务重启、承载序列缓存的进程异常终止,或通过sp_sequence_get_range获取的序列范围未被实际使用(比如事务回滚),缓存中未消耗的序列值会被直接丢弃,后续请求会从下一个缓存块的起始值开始,从而产生80-100的间隙。

另外,若存在其他业务场景调用该存储过程时传入较大的@increment值(比如100),即使事务回滚,sp_sequence_get_range获取的整个序列范围也会被标记为已使用,同样会造成大范围跳号。

二、复现方法

场景1:服务重启触发缓存丢失

  1. 创建带100大小缓存的序列(匹配跳号范围):
CREATE SEQUENCE dbo.n_TestTable
    AS BIGINT
    START WITH 1
    INCREMENT BY 1
    CACHE 100;
  1. 调用存储过程axsp_get_next_no_internal_64,传入@table_name='TestTable'、@increment=1等参数,连续调用10次,得到序列值1-10。
  2. 重启SQL Server服务。
  3. 再次调用存储过程,获取到的下一个值为101,中间11-100的间隙完全匹配用户遇到的跳号现象。

场景2:sp_sequence_get_range未使用序列范围触发跳号

  1. 使用上述序列,打开新会话执行:
DECLARE @new_no BIGINT;
EXEC dbo.axsp_get_next_no_internal_64 
    @table_name='TestTable',
    @increment=100,
    @is_use_sequence=1,
    @new_next_no=@new_no OUTPUT;
-- 此时@new_no为101,序列已预占1-100范围
ROLLBACK; -- 模拟事务回滚,未实际使用该范围
  1. 回到正常调用逻辑,传入@increment=1调用存储过程,获取到的下一个值为101,中间1-100的序列值已被消耗且未被使用,形成间隙。

场景3:会话异常终止(实例级缓存场景)

  1. 保持序列缓存为100,打开一个会话,执行多次NEXT VALUE FOR dbo.n_TestTable,获取到1-5。
  2. 强制终止该会话(比如关闭SSMS窗口、执行KILL [会话ID])。
  3. 若SQL Server实例回收了该缓存块(极端场景),后续调用存储过程会直接加载下一批缓存(101-200),导致11-100的间隙。

三、关键结论

SQL Server Sequence的设计目标是高性能生成唯一值,而非保证序列连续。缓存机制是性能优化的核心,但也是大范围跳号的主要来源。即使无异常场景,事务回滚也会导致单个或少量跳号,缓存丢失则会引发批量跳号。

内容的提问来源于stack exchange,提问作者Mayur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 16:50:23