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。我認為在達到上限之前你還有一段時間——即使你一次跳躍 100k 條記錄,你可能跳躍了 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 中。這應該會減少代理鍵中存在間隙的機會。

肯德拉·利特爾可愛的隔離等級海報幫助我記住檢查真正提交的內容需要什麼隔離等級。

在此輸入影像描述

相關內容