SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#Demo') IS NOT NULL
BEGIN
DROP TABLE #Demo;
END
CREATE TABLE #Demo
(
demoid int IDENTITY(1,1) NOT NULL
, CantBeNull varchar(50) NOT NULL
);
-- add a record and look at our identity
INSERT INTO #Demo
(CantBeNull)
VALUES
('First Entry');
SELECT SCOPE_IDENTITY() AS GeneratedId;
-- GO forces the batch to commit (assuming default implicit transaction model)
GO
-- Violate RI
INSERT INTO #Demo
(CantBeNull)
VALUES
(NULL);
SELECT SCOPE_IDENTITY() AS RIViolationGeneratedId;
GO
-- add a record and look at our identity
INSERT INTO #Demo
(CantBeNull)
VALUES
('Third Entry');
SELECT SCOPE_IDENTITY() AS ThirdGeneratedId;
GO
-- Transaction consumes
BEGIN TRAN
INSERT INTO #Demo
(CantBeNull)
VALUES
('Fourth Entry');
SELECT SCOPE_IDENTITY() AS FourthGeneratedId;
ROLLBACK;
INSERT INTO #Demo
(CantBeNull)
VALUES
('Fifth Entry');
SELECT SCOPE_IDENTITY() AS FifthGeneratedId;
GO
SELECT D.* FROM #Demo AS D;
Bigint 的范围从 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。我认为你在达到上限之前还有一段时间 - 即使你一次跳 100k 条记录,你可能有十亿次跳跃但仍然没有达到上限。如果您仍然担心,请重新设置您的身份以从负面范围开始,然后在您担心事情之前我们都已经死了。
为什么身份值有差距?
一个应用程序试图将一条记录插入到您的表中,并且从池中删除了一个数字。出于引用完整性的原因,插入失败或调用程序随后撤消(回滚)已处理的插入 - 无论哪种方式,标识值都不再在候选池中。是的,即使事务回滚,数量已经用完,也不会回滚。
自己测试
在结果选项卡中,您将看到 1、1、3、4 和 5,因为这是正在使用的数字,但由于我们回滚 4,#Demo 表的提交结果将看起来
我不喜欢这种行为
这就是标识属性的工作方式——无法更改它。如果您切换到 Sequence 对象(2012 年新增),情况也是如此。
如果差距是一个问题,我会考虑确定哪个进程正在消耗它们。如果它违反了引用完整性 (RI),请在尝试保存之前加强验证。如果根本原因是事务被回滚,则将其设为两阶段提交或类似的东西 - 保存到 Stage.MyTable。如果身份耗尽是一个问题,请切换到 SEQUENCE 对象并打开循环。定期轮询此表以获取已提交的事务,然后从那里插入到 dbo.MyTable 中。这应该会减少代理键中存在间隙的机会。
Kendra Little可爱的隔离级别海报帮助我记住我需要什么隔离级别来检查真正、真正提交的内容。