Bigint 标识列从 17 跳转到 1004。为什么?

Bigint 标识列从 17 跳转到 1004。为什么?

我在几个表上使用 bigint 标识列,并注意到它们不断从低数字跳到高数字。在本例中,从 17 跳到 1004,但在其他表中则跳到 10000。如果这种行为继续下去,我将在几千条记录内达到 bigint 的范围!为什么会发生这种情况?我该如何解决?

截图在这里:

答案1

Bigint 的范围从 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。我认为你还需要一段时间才能达到上限 - 即使你一次跳跃 10 万条记录,你也可能跳跃十亿次,但仍然无法达到上限。如果你仍然担心,请重新播种你的身份以从负范围开始,在你担心事情之前我们都会死。

身份价值为何会有差距?

应用程序尝试将记录插入到您的表中,然后从池中删除一个数字。由于引用完整性的原因,插入失败,或者调用程序随后撤消(回滚)事务插入 - 无论哪种方式,标识值都不再位于候选池中。是的,即使事务回滚,数字也已耗尽并且不会回滚。

自己测试一下

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;

在结果选项卡中,您将看到 1、1、3、4 和 5,因为这些是正在使用的数字,但由于我们将 4 回滚,因此 #Demo 表的提交结果将如下所示

demoid  CantBeNull
1       First Entry
3       Third Entry
5       Fifth Entry

我不喜欢这种行为

这就是身份属性的工作方式 - 没有办法改变它。如果您切换到 Sequence 对象(2012 年新增),情况也是如此。

如果间隙令人担忧,我会查看哪些过程正在使用它们。如果是引用完整性 (RI) 违规,请在尝试保存之前加强验证。如果根本原因是事务被回滚,则将其设为两阶段提交或类似的东西 - 保存到 Stage.MyTable。如果身份耗尽是一个问题,请切换到 SEQUENCE 对象并打开循环。定期轮询此表以查找已提交的事务,然后从那里插入 dbo.MyTable。这应该会减少代理键中存在间隙的机会。

肯德拉·利特尔可爱的隔离级别海报帮助我记住我需要什么隔离级别来检查真正提交的内容。

在此处输入图片描述

相关内容