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

kas*_*hif 117 sql sql-server identity-column sql-server-2012

FeeSQL Server 2012中的"ReceiptNo"列中的一个表中,数据库标识增量突然开始跳转到100而不是1,具体取决于以下两点.

  1. 如果它是1205446,则跳转到1206306,如果是1206321,则跳转到1207306,如果是1207314,则跳到1208306.我想让你注意的是,最后三位数保持不变,即每当跳跃时为306如下图所示.

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

在此输入图像描述

Mar*_*ith 147

您可能在这里遇到问题(回程机器).

SQL Server 2012现在IDENTITYint列中分配值时使用的缓存大小为1,000,并且重新启动服务可能会"丢失"未使用的值(缓存大小为10,000 bigint/ numeric).

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

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

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

  1. 例如,您可以使用SEQUENCE而不是标识列来定义较小的高速缓存大小,并NEXT VALUE FOR在列默认值中使用.
  2. 或者应用跟踪标志272,这使得IDENTITY分配记录在先前版本中.

您应该意识到这些变通办法都不能确保没有差距.这从来没有得到保证,IDENTITY因为它只能通过序列化插入表来实现.如果你需要一个无缝列,您需要使用不同的解决方案比任何IDENTITYSEQUENCE


Har*_*GUL 54

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

解决方案是:

  • 运行SQL Server配置管理器.

  • 选择SQL Server服务.

    SQL Server配置管理器

  • 右键单击" SQL Server",然后选择" 属性".

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

    SQL Server启动参数

  • 有没有办法将跟踪标志应用于单个数据库?我不想在整个服务器上进行此更改,因为我拥有第三方数据库,并且不确定这将如何影响它们。 (2认同)

Luk*_*zda 27

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

IDENTITY_CACHE = {ON | 关闭}

在数据库级别启用或禁用标识高速缓存.默认为ON.身份缓存用于提高具有Identity列的表的INSERT性能.为避免在服务器意外重新启动或故障转移到辅助服务器的情况下,Identity列的值存在间隙,请禁用IDENTITY_CACHE选项. 此选项与现有的SQL Server跟踪标志272类似,不同之处在于它可以在数据库级别设置,而不是仅在服务器级别设置.

(......)

G.设置IDENTITY_CACHE

此示例禁用身份缓存.

ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ;
Run Code Online (Sandbox Code Playgroud)


Jey*_*ara 24

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

在主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
Run Code Online (Sandbox Code Playgroud)

然后使用以下语法将其添加到"启动"中.

EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';
Run Code Online (Sandbox Code Playgroud)

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


小智 14

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

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

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

最重要的是,如果您使用的是Sql Server 2008R2,那么请保持打开状态.说真的,坚持下去.直到微软承认他们引入了一个巨大的错误,即使在Sql Server 2016中它仍然存在,那么我们不应该升级,直到他们拥有它并修复它.

微软直接引入了一个重大改变,即他们打破了一个不再按设计工作的工作API,因为他们的系统在重启时忘记了他们当前的身份.缓存或没有缓存,这是不可接受的,并且名为Bryan的Microsoft开发人员需要拥有它,而不是告诉全世界它是"按设计"和"功能".当然,缓存是一个功能,但失去了下一个身份应该是什么,不是一个功能.这是一个fricken 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)
Run Code Online (Sandbox Code Playgroud)

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

祝好运.


Seb*_*ine 7

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

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

你可以在这里找到更多相关信息:http://sqlity.net/en/792/the-gap-in-the-identity-value-sequence/