身份增量在SQL Server数据库中跳跃

在我的一个表中,SQL Server 2012数据库标识增量中的“ReceiptNo”列中的Fee突然开始跳到100而不是1,具体取决于以下两点。

  1. 如果是1205446,则跳转到1206306,如果是1206321,则跳转到1207306,如果是1207314,则跳转到1208306.我要说明的是,最后三位数字保持不变,即每跳跃306次如下图所示。

  2. 当我重新启动我的电脑时会发生此问题

在这里输入图像描述

你可能在这里遇到这个问题。

当在int列中分配IDENTITY值时,SQL Server 2012现在使用的caching大小为1,000,并且重新启动服务可以“丢失”未使用的值(对于bigint / numeric ,caching大小为10,000)。

从你显示的数据看起来像是在12月22日的数据input之后发生的,然后当它重新启动时,SQL Server保留了值1206306 - 1207305 。 在12月24日至25日的数据input完成后,再次重新启动,SQL Server保留下一个范围1207306 - 1208305在28日的条目中可见。

除非以不寻常的频率重新启动服务,否则任何“丢失”值都不会在数据types所允许的值的范围内产生任何显着的影响,所以最好的策略是不要担心。

如果这是由于某种原因,一个真正的问题,你看到链接连接项目线程上的解决方法。

  1. 您可以使用SEQUENCE而不是标识列,并定义一个较小的caching大小,例如在列默认NEXT VALUE FOR中使用NEXT VALUE FOR
  2. 或者应用跟踪标志272,这使得IDENTITY分配与先前版本一样被logging。

你应该知道这些解决方法都不能保证没有差距。 这从来没有被IDENTITY保证,因为只有通过序列化插入到表中才可能。 如果您需要无间隙柱,则需要使用与IDENTITYSEQUENCE不同的解决scheme

重新启动SQL Server后,会出现此问题。

解决scheme是:

  • 运行SQL Serverconfigurationpipe理器

  • selectSQL Server服务

    SQL Server配置管理器

  • 用鼠标右键单击SQL Server并select属性

  • 在“ 启动参数”下的打开窗口中,键入-T272 ,然后单击添加 ,然后按应用button并重新启动。

    SQL Server启动参数

我知道我的答案可能迟到了。 但我已经通过在SQL Server 2012中添加启动存储过程以另一种方式解决了。

在主数据库中创build以下存储过程。

 USE [master] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[ResetOrderIdentityAfterRestart] AS BEGIN begin TRAN declare @id int = 0 SELECT @id = MAX(id) FROM [DatabaseName].dbo.[TableName] --print @id DBCC CHECKIDENT ('[DatabaseName].dbo.[TableName]', reseed, @id) Commit END 

然后通过使用以下语法将其添加到启动。

 EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on'; 

如果你有几张桌子,这是一个好主意。 但如果你必须为许多表格做,这种方法仍然有效,但不是一个好主意。

跳跃身份值有很多可能的原因。 它们从回滚插入到用于复制的身份pipe理。 什么导致你的情况,我不能没有花一些时间在你的系统。

但是,你应该知道,绝不可以假设一个身份栏是contiguos。 有太多东西可以导致差距。

你可以在这里find更多的信息: http : //sqlity.net/zh/792/the-gap-in-the-identity-value-sequence/

SQL Server 2017+可以使用ALTER DATABASE SCOPED CONFIGURATION :

IDENTITY_CACHE = {ON | OFF}

在数据库级别启用或禁用身份caching。 默认是ON。 身份caching用于提高具有标识列的表上的INSERT性能。 要避免在服务器意外重新启动或故障切换到辅助服务器的情况下Identity列的值出现空白,请禁用IDENTITY_CACHE选项。 该选项类似于现有的SQL Server跟踪标志272,除了它可以在数据库级而不是在服务器级设置。

(……)

G.设置IDENTITY_CACHE

此示例禁用身份caching。

 ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ; 

无论大小如何,这仍然是许多开发人员和应用程序中非常常见的问题。

不幸的是,上面的build议并没有解决所有的情况,即共享主机,你不能依靠你的主机来设置-t272启动参数。

此外,如果您有现有的表使用主键的这些标识列,那么删除这些列并重新创build新列以使用BS序列解决方法是一个巨大的努力。 如果您在SQL 2012+中devise新的表,那么序列变通方法才是有效的

底线是,如果你在Sql Server 2008R2上,那就留在IT上吧。 真的,留下来吧。 在微软承认他们引入了一个巨大的bug之前,即使在Sql Server 2016中也是如此,那么我们就不应该升级,直到拥有它并修复它。

微软直接推出了一个突破性的变化,即他们打破了一个工作的API,不再按照devise工作,因为他们的系统在重启时忘记了他们当前的身份。 caching或没有caching,这是不可接受的,并且Bryan名字的微软开发者需要拥有它,而不是告诉世界它是“被devise”和“特点”。 当然,高速caching是一个function,但是对下一个身份应该是什么也不知道,这不是特色。 这是一个fricken的BUG!

我将分享我使用的解决方法,因为我的数据库在共享主机服务器上,而且我不会丢弃和重新创build我的主键列,这将是一个巨大的PITA。

相反,这是我可耻的破解(但不像微软已经引入的POS错误)。

哈克/修复:

在插入命令之前,只需在每次插入之前填写您的身份。 只有在您没有对Sql Server实例进行pipe理控制的情况下才推荐此修复程序,否则我build议重新启动服务器。

 declare @newId int -- where int is the datatype of your PKey or Id column select @newId = max(YourBuggedIdColumn) from YOUR_TABLE_NAME DBCC CheckIdent('YOUR_TABLE_NAME', RESEED, @newId) 

就在你插入之前的那三行,你应该很好走。 这实际上不会影响到性能,也就是说它不会被忽视。

祝你好运。