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

介绍

从 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;

此时结果和我们预期的一样。 现在重启你的 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种解决方案将会影响此服务实例上的所有数据库。

此文为译文(英文水平有限,望谅解),原文链接:SQL Server 2012 Auto Identity Column Value Jump Issue

时间: 2024-10-10 17:31:02

SQL Server 2012 自动增长列,值跳跃问题的相关文章

SQL Server 2012自动备份

SQL 2012和2008一样,都可以做维护计划,来对数据库进行自动的备份. 现在做这样一个数据库维护的计划,每天0点对数据库进行差异备份,每周日0点对数据库进行完全备份,并且每天晚上10点删除一次过期备份(两个星期前的). 做这样一个维护计划的方法如下: 在做计划之前,需要先启用SQL Server代理,并将启动模式设为自动. 接下来,依次点击“SQL Server Management Studio”--“管理”--“维护计划”--“维护计划向导”--“维护计划向导” 在这里由于这里有三项计

SQL Server 文件自动增长那些事

方法 1. 把文件的增长设置为按照固定大小增长. 如filegrowth = 100MB; ---------------------------------------------------------------------------------------------------------------------------------------------------------- 数据文件增长说明. 比如说表 T 建立在文件file1 和 file2 上.file1 file2

Sql Server实现自动增长

在学习中遇到这个问题 数据库里有编号字段 BH00001 BH00002 BH00003 BH00004 如何实现自动增长 --下面的代码生成长度为8的编号,编号以BH开头,其余6位为流水号. --得到新编号的函数 CREATE FUNCTION f_NextBH() RETURNS char(8) AS BEGIN RETURN(SELECT 'BH'+RIGHT(1000001+ISNULL(RIGHT(MAX(BH),6),0),6) FROM tb WITH(XLOCK,PAGLOCK)

SQL Server 编写自动增长的字符串型主键

1.编写标量值函数ICONVERT2STRING CREATE FUNCTION ICONVERT2STRING(@N INT,@F INT) RETURNS VARCHAR(10) AS BEGIN DECLARE @M INT DECLARE @L0 INT DECLARE @CH VARCHAR(10) DECLARE @ST VARCHAR(20) SELECT @CH='' SELECT @ST=CONVERT(VARCHAR(10),@N) SELECT @ST=RTRIM(@ST)

sql server 2012 行转列

table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) 对于一个字段的汇总和转置,只用一次. ) tb pivot(max(copies) for ORDER_TYPE in ([11],[12],[13],[14])) tb 对于多个字段的汇总和转置,要嵌套多次. ) tb pivot(max(copies) for ORDER_TYPE in ([11],[12],[13],[14])) tb

SQL SERVER 中在自动增长列中插入值

如果想在自动增长列中插入值,如果没有设置 IDENTITY_INSERT 为 ON 的话会出现如下错误 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'dbo.table' 中的标识列插入显式值. 解决问题的办法是: SET IDENTITY_INSERT [TableName] ON 在插入完成以后可以通过: SET IDENTITY_INSERT [TableName] OFF 关闭 IDENTITY_INSERT

使用sql语句创建修改SQL Server标识列(即自动增长列)

一.标识列的定义以及特点SQL Server中的标识列又称标识符列,习惯上又叫自增列.该种列具有以下三种特点:1.列的数据类型为不带小数的数值类型2.在进行插入(Insert)操作时,该列的值是由系统按一定规律生成,不允许空值3.列值不重复,具有标识表中每一行的作用,每个表只能有一个标识列.由于以上特点,使得标识列在数据库的设计中得到广泛的使用.二.标识列的组成创建一个标识列,通常要指定三个内容:1.类型(type)在SQL Server 2000中,标识列类型必须是数值类型,如下:decima

SQL获取刚插入的记录的自动增长列ID的值

假设表结构如下: CREATE TABLE TestTable ( id int identity, CreatedDate datetime ) SQL2005获得新增行的自动增长列的语句如下: insert into TestTable (CreatedDate)  output  inserted.id  values (getdate()) SQL2000获得新增行的自动增长列的语句如下: insert into TestTable (CreatedDate)  values (getd

Sql Server中的标识列(自增长字段)

一.标识列的定义以及特点 SQL Server中的标识列又称标识符列,习惯上又叫自增列.该种列具有以下三种特点: 1.列的数据类型为不带小数的数值类型2.在进行插入(Insert)操作时,该列的值是由系统按一定规律生成,不允许空值3.列值不重复,具有标识表中每一行的作用,每个表只能有一个标识列. 由于以上特点,使得标识列在数据库的设计中得到广泛的使用. 二.标识列的组成创建一个标识列,通常要指定三个内容:1.类型(type)在SQL Server 2000中,标识列类型必须是数值类型,如下:de