sqlserver 自增列(id)跳跃问题,一下就跳过一千多个id

前言:sql server新建的表,设置id为主键,自增+1,第一天用还好好的,id到自增到几十,第二天用的时候,id突然变成了一千多,这太令人郁闷了,搜索一下,发现有个老外给出了答案。


SQL Server 2012 自动标识列值跳转问题

介绍
从 SQL Server 2012 版本开始,当 SQL Server 实例重新启动时,将Identity 跳转表的 值,实际跳转的值取决于标识列数据类型。如果是整数( int) 数据类型,则跳转值为 1000 ,如果是大整数( bigint) ,则跳转值为 10000。从我们的应用来看,这种增量并不是所有业务案例都可以接受的,特别是当价值展示给客户时。这是仅 SQL Server 2012 附带的特殊情况/问题,旧版本没有此类问题。

背景
几天前,我们的 QA 工程师声称我们表的一个标识列 jumped 10000。这意味着该表的最后一个标识值 2200 现在是 12001。在我们的业务逻辑中,就像价值展示给客户端一样,它不会被客户端接受。所以我们必须解决这个问题。

使用代码
第一次,我们都感到惊讶和困惑,这怎么可能?我们通常不会在标识列中插入任何值(可以向标识列插入值)。标识值由 SQL Server 本身维护。我们的一名核心团队成员开始调查问题并找到了解决方案。现在,我想详细说明我的同事发现的问题和解决方案。

如何重现?
您需要设置 SQL Server 2012 并创建一个测试数据库。然后创建一个带有自动标识列的表:

创建 表 MyTestTable(Id  int  Identity ( 1 , 1 ), Name  varchar ( 255 ));

现在在那里插入 2 行:

插入 到 MyTestTable(名称) 值 (' Mr.Tom'); 插入 到 MyTestTable(名称) 值 ('杰克逊先生');

你会看到结果:

SELECT  Id, Name  FROM  MyTestTable;

结果如预期。现在只需重新启动您的 SQL Server 服务。有多种方法可以做到这一点。我们是从 SQL Server 管理工作室完成的。

sqlserver 自增列(id)跳跃问题,一下就跳过一千多个id

 

现在,再次向同一个表中插入另外 2 行:

插入 到 MyTestTable(名称) 值 (' Mr.Tom2'); 插入 到 MyTestTable(名称) 值 (' Mr.Jackson2');

现在看结果:

SELECT  Id, Name  FROM  MyTestTable;


现在您看到,在重新启动 SQL Server 2012 实例后,标识值以 1002. 这意味着它跳了 1000。前面我说我们也看那个标识列的数据类型是不是 bigint,那么就会跳转 10000。

真的是bug吗?

Microsoft 宣称这是一项功能而不是错误,并且在许多情况下它会有所帮助。但在我们的例子中,这是不可接受的,因为该数字会显示给客户端,并且客户端会惊讶地看到跳转后的新数字,而新数字取决于 SQL Server 重新启动的次数。如果它对客户端不可见,那么它可能是可以接受的,以便在内部使用该号码。

解决方案

如果我们对这个所谓的功能不感兴趣,那么我们可以做两件事来阻止这种跳跃。

使用序列
将 -t272 注册到 SQL Server 启动参数
使用序列

首先,我们需要Identity 从表中删除 列。然后创建一个没有缓存功能的序列并从该序列中插入数字。以下是代码示例:

CREATE  SEQUENCE  Id_Sequence  AS  INT  START  WITH  1  INCREMENT  BY  1  MINVALUE  0  NO MAXVALUE NO CACHE
 
插入 到 MyTestTable 值中(NEXT VALUE  FOR  Id_Sequence,  ' Mr.Tom' );
插入 到 MyTestTable 值中(NEXT VALUE  FOR  Id_Sequence,  ' Mr.Jackson' );

将 -t272 注册到 SQL Server 启动参数
从您的服务器打开 SQLServer 配置管理器。选择 SQL Server 2012 instance there right client 并选择 Properties 菜单。您将找到一个选项卡式对话窗口。您从那里选择启动参数选项卡并注册 -t272。然后再次重启SQL Server 2012实例,看看区别:

 

 

兴趣点
如果太多表包含数据库的标识列并且都包含现有值,那么最好采用解决方案 2。因为它是一个非常简单的解决方案,其范围是服务器明智的。这意味着如果您在那里添加 SQL Server 2012 参数 -t272,那么它将影响您在那里的所有数据库。如果你想创建一个新的数据库并且你需要自动生成的数字字段,那么你可以使用解决方案 1,这意味着使用列的序列值而不是自动标识值。你可以在网上找到很多关于在使用序列和优点/缺点时何时使用自动标识列的文章。我希望你能阅读所有这些并做出适当的决定。

 

解决办法:

 

1 打开配置管理器

2左面点击sql服务

3右面 右键点击SQL Server(MSSQLSERVER)

4点击 启动参数

5 在参数 里输入 -T272 点增加

上一篇:shell sed awk 替换文本内容


下一篇:mongo数据库连接工具类(C#)