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

时间:2013-01-03 19:52:32

标签: sql sql-server sql-server-2012 identity-column

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

  1. 如果是1205446,则跳转到1206306,如果是1206321,则跳转到1207306,如果是1207314,则跳到1208306.我想让你注意到的是最后三位数字仍然存在每当跳跃发生时,常数即为306,如下图所示。

  2. 重新启动计算机时出现此问题

  3. enter image description here

6 个答案:

答案 0 :(得分:140)

You are probably encountering the issue here (wayback machine).

IDENTITY列中分配int值时,SQL Server 2012现在使用的缓存大小为1,000,重新启动服务可能会“丢失”未使用的值({1}的缓存大小为10,000 } / bigint)。

根据您显示的数据,看起来这发生在12月22日的数据输入之后,然后重新启动时SQL Server保留了值numeric。在12月24日至25日的数据输入完成后,另一次重启,SQL Server保留了第28个条目中可见的下一个范围1206306 - 1207305

除非您以异常频率重新启动服务,否则任何“丢失”值都不可能对数据类型允许的值范围产生任何重大影响,因此最好的策略是不必担心它。

如果出于某种原因这是一个真正的问题,请查看链接的Connect Item线程的变通方法。

  1. 您可以使用SEQUENCE代替标识列并定义较小的缓存大小,并在列默认值中使用1207306 - 1208305
  2. 或应用跟踪标志272,使NEXT VALUE FOR分配记录为先前版本。
  3. 您应该知道这些变通方法都不能确保没有差距。 IDENTITY从未保证这一点,因为只有将插入序列化到表中才能实现。如果您需要无间隙色谱柱,则需要使用与IDENTITYIDENTITY

    不同的解决方案

答案 1 :(得分:49)

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

解决方案是:

  • 运行 SQL Server配置管理器

  • 选择 SQL Server服务

    SQL Server Configuration Manager

  • 右键单击 SQL Server 并选择属性

  • 启动参数下的打开窗口中,输入-T272并点击添加,然后按应用按钮,重新启动。

    SQL Server startup parameters

答案 2 :(得分:23)

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

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

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[ResetTableNameIdentityAfterRestart]
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';

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

答案 3 :(得分:21)

function change() { console.log("Started"); var x = document.getElementById('A').value; document.getElementById('List').list = x; var check = document.getElementById('List').list if (check === x) { console.log("Complete"); } else { console.log("Failed"); } } ,您可以使用ALTER DATABASE SCOPED CONFIGURATION

  

IDENTITY_CACHE = {ON |关闭}

     

在数据库级别启用或禁用身份缓存。默认   是ON。身份缓存用于提高INSERT性能   具有标识列的表。 避免价值观的差距   服务器意外重启的情况下的标识列或   故障转移到辅助服务器,禁用IDENTITY_CACHE选项。   此选项类似于现有的SQL Server跟踪标志272,   除了可以在数据库级别设置,而不是仅在   服务器级别。

     

(...)

     

<强“G。设置IDENTITY_CACHE

     

此示例禁用身份缓存。

SQL Server 2017+

答案 4 :(得分:12)

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

不幸的是,上述建议并未修复所有方案,即共享主机,您不能依赖主机设置-t272启动参数。

此外,如果您有现有的表使用这些标识列作为主键,那么删除这些列并重新创建新列以使用BS序列解决方法是一项巨大的工作。只有在SQL 2012 +

中从头开始设计表时,序列解决方法才有用

如果您使用的是Sql Server 2008R2,则可以选择STAY ON IT。说真的,坚持下去。直到微软承认他们引入了一个巨大的错误,即使在Sql Server 2016中仍然存在,我们不应该升级,直到他们拥有它并修复它。

微软直接推出了一项重大改变,即他们打破了一个不再按设计工作的工作API,因为他们的系统在重启时忘记了他们当前的身份。缓存或没有缓存,这是不可接受的,并且名为Bryan的Microsoft开发人员需要拥有它,而不是告诉全世界它是“按设计”和“功能”。当然,缓存是一个功能,但失去了下一个身份应该是什么,不是一个功能。这是一个混乱的BUG !!!

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

相反,这是我可耻的黑客攻击(但不像微软推出的这个POS错误那样可耻)。

哈克/修复:

在插入命令之前,只需在每次插入之前重新设置您的标识。如果您没有对Sql Server实例的管理控制,则仅建议使用此修复程序,否则我建议重新启动服务器。

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)

在你插入之前的那3行,你应该好好去。它确实不会对性能产生太大影响,即它不会引起注意。

古德勒克。

答案 5 :(得分:7)

跳转身份值有很多可能的原因。它们包括从回滚插入到复制的身份管理。在你的情况下造成这种情况的原因是我不能在你的系统中花费一些时间。

但是,您应该知道,在任何情况下,您都不能假定身份列为contiguos。有太多东西可能导致差距。

您可以在此处找到有关此内容的更多信息:http://sqlity.net/en/792/the-gap-in-the-identity-value-sequence/