Sql-Server

在巨大的事務數據庫中,如何在巨大的負載下將主鍵的數據類型從 int 更改為 bigint?

  • September 9, 2016

這是一個遺留系統,一個表中有超過 10 億條記錄,每天要處理 1000 萬次事務。

現在應用程序抱怨:

將 IDENTITY 轉換為數據類型 int 的算術溢出錯誤

我們想將該id列的數據類型更改為bigint,但它不能這樣做並且超時。

我們應該做什麼?我一點頭緒都沒有。我們不能停止系統,因為它是一個單一的應用程序和數據庫,可以做很多事情。因此,我們不希望停止整個系統。

我們正在使用 SQL Server 10.50.6000.34,即 SQL Server 2008 R2 SP3(2014 年 9 月)

假設您目前的表類似於

CREATE TABLE YourTable
 (
    Id           INT IDENTITY PRIMARY KEY,
    OtherColumns VARCHAR(10)
 )

並且您現有的引用該表的程式碼僅針對該表執行基本的 DQL 和 DML 命令(即SELECT/ UPDATEMERGEINSERTDELETE

YourTable(Id)在任何地方都沒有被外鍵引用。

那麼可能快速啟動和執行的最佳方法(如果您無法承受一次性重建整個表的停機時間)將重命名該表(例如 as YourTableInt)並創建一個新表

CREATE TABLE YourTableBigInt
 (
    Id           BIGINT IDENTITY(2147483648, 1) PRIMARY KEY,
    OtherColumns VARCHAR(10)
 )

然後,您可以創建一個與原始表名同名的視圖。

CREATE VIEW YourTable
AS
 SELECT Id,
        OtherColumns
 FROM   YourTableInt
 UNION ALL
 SELECT Id,
        OtherColumns
 FROM   YourTableBigInt 

您需要編寫INSTEAD OF將插入/更新/刪除路由到適當表的觸發器。這最初可能基於 Id 是否 <= 2147483647 ,但如果您嘗試在後台將行從舊表遷移到新表,那麼這將不起作用,因此最好執行以下操作。

刪除觸發器 通過加入 id 對兩個表應用刪除

更新觸發器 通過加入 id 將更新應用於兩個表

插入觸發器 將所有插入路由到新的“YourTableBigInt”表中。通過視圖插入應該不可能輸入可能與原始表中的任何內容衝突的顯式標識,因為任何嘗試都set identity_insert YourTable將失敗,因為它實際上是一個視圖。

然後,您可以有一個後台程序YourTableIntoutputYourTableBigInt. 一旦原始表為空,您可以刪除它和視圖並將 YourTableBigInt 重命名為 YourTable。

作為臨時解決方案,因為您說您不能關閉系統,至少可能在短時間內…

請記住,數據類型是帶符號的 INT(pos2bil 到 neg2bil),這意味著允許 40 億條記錄,而不僅僅是 20 億條。所以,為什麼不考慮做一個 DBCC CHECKIDENT 來改變身份以從負 nbrs 增加,然後讓它去另外 20 億條記錄,直到你弄清楚該怎麼做。這應該是一個快速修復。

希望您不應該將 IDENT 用於除 FK 之外的任何業務目的,例如 order by,如果 IDENT 是 CLUST,則關心磁碟上記錄的順序。

對使用 nonegative nbrs 的某些考慮非常小心….但是您處於困境中,這可能對您有用,所以我只是提供一個出路的想法…

這是我不喜歡 IDENT 的簽名數據類型的事情之一,即 20 億個條目的“失去”。

引用自:https://dba.stackexchange.com/questions/148730