Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server数据库中的标识增量正在跳跃_Sql_Sql Server_Sql Server 2012_Identity Column - Fatal编程技术网

SQL Server数据库中的标识增量正在跳跃

SQL Server数据库中的标识增量正在跳跃,sql,sql-server,sql-server-2012,identity-column,Sql,Sql Server,Sql Server 2012,Identity Column,在我的一个表中,SQL Server 2012中“ReceiptNo”列中的Fee,数据库标识增量突然开始跳到100,而不是1,这取决于以下两个方面 如果是1205446,则跳至1206306;如果是1206321,则跳至1207306;如果是1207314,则跳至1208306。我想让你们注意的是,最后三位数字保持不变,即当跳跃发生时,306,如下图所示 重新启动计算机时会出现此问题 由于SQL Server 2012年以来的性能改进,您遇到了这种行为 现在,当为int列分配IDENTITY值

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

  • 如果是1205446,则跳至1206306;如果是1206321,则跳至1207306;如果是1207314,则跳至1208306。我想让你们注意的是,最后三位数字保持不变,即当跳跃发生时,306,如下图所示

  • 重新启动计算机时会出现此问题


  • 由于SQL Server 2012年以来的性能改进,您遇到了这种行为

    现在,当为
    int
    列分配
    IDENTITY
    值时,默认情况下,它使用1000的缓存大小,并且重新启动服务可能会“丢失”未使用的值(对于
    bigint
    /
    数值
    ,缓存大小为10000)

    这一点在本节中提到

    SQL Server可能会出于性能原因和 在数据库发生故障或发生故障时,某些指定的值可能会丢失 服务器重启。这可能会导致标识值出现缺口 插入。如果间隙不可接受,则应用程序应使用其 拥有生成键值的机制。使用带有
    NOCACHE
    选项可以将间隙限制为从不存在的事务 承诺

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

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

    如果这对你来说是一个真正的问题,一些可能的解决方法是

  • 您可以使用而不是标识列,并定义较小的缓存大小,例如,在列默认值中为使用下一个值
  • 或者应用跟踪标志272,使
    标识
    分配作为2008 R2之前的版本记录。这适用于所有数据库
  • 或者,对于最新版本,执行
    ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY\u CACHE=OFF
    以禁用特定数据库的标识缓存

  • 您应该知道,这些解决方法都不能保证没有差距。
    IDENTITY
    从来不能保证这一点,因为只有将插入序列化到表中才能实现。如果需要无间隙列,则需要使用不同于
    IDENTITY
    SEQUENCE

    的解决方案,可能有许多原因导致标识值跳转。它们的范围从回滚插入到复制的身份管理。在你的情况下,如果不花点时间在你的系统中,我就说不出是什么导致了这种情况

    但是,您应该知道,在任何情况下都不能假定标识列是contiguos。有太多的事情会造成差距


    您可以在此处找到有关此问题的更多信息:

    此问题发生在重新启动SQL Server之后

    解决办法是:

    • 运行SQL Server配置管理器

    • 选择SQL Server服务

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

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


      • 我知道我的回答可能会迟到。但我用另一种方式解决了这个问题,在SQLServer2012中添加了一个启动存储过程

        在master DB中创建以下存储过程

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

        如果你没有几张桌子,这是个好主意。但是,如果必须对许多表执行此操作,此方法仍然有效,但不是一个好主意。

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

        不幸的是,上述建议并不能解决所有情况,即共享主机,您不能依靠您的主机来设置-t272启动参数

        此外,如果现有表使用这些标识列作为主键,那么删除这些列并重新创建新列以使用BS序列解决方案将是一项巨大的工作。只有在SQL 2012中从头开始设计新表时,顺序解决方案才是好的+

        底线是,如果您使用的是SQLServer2008R2,那么请继续使用它。说真的,坚持下去。除非微软承认他们引入了一个巨大的漏洞,即使在Sql Server 2016中仍然存在,否则我们不应该升级,直到他们拥有并修复它

        微软直接引入了一个突破性的改变,即他们破坏了一个不再按设计工作的API,因为他们的系统在重启时忘记了他们当前的身份。缓存或不缓存,这是不可接受的,微软开发人员布莱恩需要拥有它,而不是告诉世界它是“设计”和“功能”。当然,缓存是一项功能,但忘记下一个标识应该是什么并不是一项功能。这是一只飞虫

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

        相反,这是我可耻的黑客行为(但不像微软引入的POS错误那样可耻)

        破解/修复: 在插入命令之前,只需在每次插入之前重新设定标识的种子。此修复程序只是建议的
        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)
        
        ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ;