当前位置:首页 > 技术心得 > 正文内容

SQL Server 2012 自动增长列,值跳跃问题(自增增加1000)【转载】

xjtudll3年前 (2023-11-08)技术心得6480

介绍

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

背景

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

代码使用

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

如何重现此bug

你需要安装SQL Server 2012 然后创建一个测试数据库。之后再创建一个带有自增列的表格:

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

现在插入两条数据:

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

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

查看结果:

SELECT Id, Name FROM MyTestTable;

464634-20160315105002787-2110076472[1]

此时结果和我们预期的一样。 现在重启你的 SQL Server Service。重启SQL服务有多种方法,我们这里通过 SQL Server 管理器来重启:

464634-20160315103556256-699496677[1]

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

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

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

查看结果:

SELECT Id, Name FROM MyTestTable;

464634-20160315104909271-1107098834[1]

现在你看到重启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重现的操作,验证问题是否已解决。

464634-20160315104055928-298109471[1]

额外说明

如果在你的数据库中有很多自增列的表,并且这些表都存在数值跳跃问题,那么采用第2种方案更好一些。因为它非常简单,并且作用域是服务器级别的。采用第2种解决方案将会影响此服务实例上的所有数据库。

扫描二维码推送至手机访问。

版权声明:本文由鸟的天空发布,如需转载请注明出处。

本文链接:http://xjtudll.cn/Exp/659/

标签: SQL
分享给朋友:

“SQL Server 2012 自动增长列,值跳跃问题(自增增加1000)【转载】” 的相关文章

模数转换器的分类

直接ADC是将输入模拟电压直接转换成数字量,如并联比较型ADC和逐次比较型ADC; 间接ADC是先将输入模拟电压转换成时间或频率,然后再把这些中间量转换成数字量,如双积分型ADC。 并联比较型ADC 优点:采用各量级同时并行比较,各位输出码同时并行产生,因此转换速度快,转换速度与输出码位数无关...

运放主要参数

集成运放的参数较多,其中主要参数分为直流指标和交流指标。 其中主要直流指标有输入失调电压、输入失调电压的温度漂移(简称输入失调电压温漂)、输入偏置电流、输入失调电流、输入偏置电流的温度漂移(简称输入失调电流温漂)、差模开环直流电压增益、共模抑制比、电源电压抑制比、输出峰-峰值电压、最大共模输入电压...

Keil C51某些汉字不显示bug解决

Keil C51某些汉字不显示bug解决

这个问题是在用ST7920 LCD 12864时发现的,“星期三”中的“三”字显示不出来。经查,发现是Keil编译器的问题,编译器在编译汉字时会将汉字内码0xFD给过滤掉,导致汉字显示不正常。 一、直接用汉字编码 如果直接用编码则不会有这个问题。例如,...

手表防水扫盲

手表防水扫盲

手表防水的误区 很多人觉得奇怪,当要购买水中活动可以使用的手表时,为何推荐他们防水100m以上的手表。“我一辈子也没潜水超过50m”,其实,这样的疑问不只存在于一般购买手表的消费者身上,前几年多数的手表销售员与修表师傅也都不甚在意这个问题,直到最近运动表的市场受到重视,才开始注意防水标示的区别,但...

TM87系列单片机使用及注意事项

TM87系列单片机使用及注意事项

一、宏的使用 1、.define 可使用在任意地方,但.EQU只能在RAM区和常数区使用。 2、宏调用时,前面必须有空格。否则提示:DUPLICATE LABEL。如图所示。   二、LCD的使用 1、首先,Mask Option里面,LCD要是启用的。不然折腾半天也是瞎折腾。设置Mas...

Proteus 7.6SP4破解1.0完美补丁

Proteus7.6支持MSP430,相信大家都知道,但是网上的破解要么不支持中文系统,要么自动退出,今天终于找到了一款中文操作系统下能用的不自动退出的破解了。这个是国内一牛人破解的,以前都是国外的牛人破解的,所以很多只支持英文系统。Proteus7.6SP4下载地址:http://rapidsha...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。