SQL Server数据库中的标识增量正在跳跃
在我的一个表中,SQL Server 2012中“ReceiptNo”列中的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值
Fee
,数据库标识增量突然开始跳到100,而不是1,这取决于以下两个方面
由于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
除非您以异常频率重新启动服务,否则任何“丢失”值都不太可能在数据类型允许的值范围内产生任何重大影响,因此最好的策略是不要担心它
如果这对你来说是一个真正的问题,一些可能的解决方法是
标识
分配作为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 ;