SQL Server 2012 自动增加列,值跳跃问题

此文为译文(英文水平有限),原文连接:SQL Server 2012 Auto Identity Column Value Jump Issue数据库

 

介绍缓存

从 SQL Server 2012 版本开始, 当SQL Server 实例重启以后,表格的自动增加列的值会发生跳跃,而具体的跳跃值的大小是根据增加列的数据类型而定的。若是数据类型是 整型(int),那么跳跃值为 1000;若是数据类型为 长整型(bigint),那么跳跃值为 10000。从咱们的项目来看,这种跳跃问题是不能被接受的,尤为是展现在客户端的时候。这个奇怪的问题只在 SQL Server 2012 及更高的版本中存在,SQL Server 2012以前版本不存在此问题。服务器

 

背景测试

几天前,咱们QA组的同事提出: 咱们表格的自增列的值莫名奇妙的跳跃了 10000。也就是说,咱们以前表格自增列的最后一个值为 2200,而如今新增一条记录,自增列的值却直接变成了 12200。在咱们的业务逻辑中像这样的状况是不容许展示在客户端的,所以咱们要解决此难题。spa

 

代码使用code

刚开始咱们都很奇怪,这是怎么发生的?咱们一般不会手动向自增列插入任何值(向自增列手动插入值是能够的),自增列的值是由数据库自行维护的。咱们核心团队的一位成员开始研究这个问题并找到了答案。如今,我想详细讲解下这个问题,以及我同事找到的解决方案。blog

 

如何重现此bugip

你须要安装SQL Server 2012 而后建立一个测试数据库。以后再建立一个带有自增列的表格:作用域

create table MyTestTable(Id int Identity(1,1), Name varchar(255));

如今插入两条数据:get

insert into MyTestTable(Name) values ('Mr.Tom');
insert into MyTestTable(Name) values ('Mr.Jackson'); 

查看结果:

SELECT Id, Name FROM MyTestTable;

 

此时结果和咱们预期的同样。 如今重启你的 SQL Server Service。重启SQL服务有多种方法,咱们这里经过 SQL Server 管理器来重启:

 

重启以后,咱们向刚才的表格再插入2条数据:

insert into MyTestTable(Name) values ('Mr.Tom2');
insert into MyTestTable(Name) values ('Mr.Jackson2');

查看结果:

SELECT Id, Name FROM MyTestTable;

 

如今你看到重启SQL Server 2012 以后的结果,它的自增列的值从1002开始了。 也就是跳跃了 1000。以前说过,若是咱们自增列的数据类型是 长整型(bigint)的话,它的跳跃值就将会是 10000。

 

它真的是个BUG吗?

微软声明这是一个功能而并不是bug, 在不少场景下是颇有用处的。 可是在咱们的案例中,咱们并不须要这样的一个功能,由于这个自增数据是要展现给客户的,客户若是看到这样跳跃性的数据,他们会感到很奇怪。而且跳跃值是根据你重启SQL Server的次数决定的。若是此数据不向客户展现,或许还能够接受。所以此功能一般只适合在内部使用。

 

解决方案

若是咱们对微软提供的这个 “功能” 不感兴趣,咱们能够经过两种途径来关闭它。

1. 使用序列 (Sequence)

2. 为SQL Server 注册启动参数 -t272

 

使用序列

首先,咱们须要移除表格的自增列。而后建立一个不带缓存功能的序列,根据此序列插入数值。 下面是示例代码:

CREATE SEQUENCE Id_Sequence
    AS INT
    START WITH 1
    INCREMENT BY 1
    MINVALUE 0
    NO MAXVALUE
   NO CACHE
insert into MyTestTable values(NEXT VALUE FOR Id_Sequence, 'Mr.Tom'); 
insert into MyTestTable values(NEXT VALUE FOR Id_Sequence, 'Mr.Jackson'); 

 

注册启动参数 -t272

打开SQL Server配置管理器。 选择 SQL Server 2012 实例,右键, 选择属性菜单。在弹出的窗口中找到启动参数,而后注册 -t272。 完成以后重启下图中的SQL Server(SQLSERVER2012), 以后进行bug重现的操做,验证问题是否已解决。

 

额外说明

若是在你的数据库中有不少自增列的表,而且这些表都存在数值跳跃问题,那么采用第2种方案更好一些。由于它很是简单,而且做用域是服务器级别的。采用第2种解决方案将会影响此服务实例上的全部数据库。

相关文章
相关标签/搜索