在SQL Server 2012版本中,當重新啟動SQL Server實例時,表的身份值將被跳轉,而實際跳轉的值取決於身份列數據類型。 如果是整數(int)數據類型,則跳轉值為1000;如果為大整數(bigint),則跳轉值為10000。從我們的應用程式角度來看,此增量不適用於所有業務案例,尤其是當... ...
簡介
在SQL Server 2012版本中,當重新啟動SQL Server實例時,表的身份值將被跳轉,而實際跳轉的值取決於身份列數據類型。 如果是整數(int)數據類型,則跳轉值為1000;如果為大整數(bigint),則跳轉值為10000。從我們的應用程式角度來看,此增量不適用於所有業務案例,尤其是當該值 向客戶展示。 這是僅SQL Server 2012附帶的特殊情況/問題,較早的版本沒有此問題。
背景
幾天前,我們的質量檢查工程師聲稱,表的標識列之一跳了10000。這意味著該表的最後一個標識值是2200,現在是12001。在我們的業務邏輯中,該值向客戶顯示了 不會被客戶接受。 因此,我們必須解決這個問題。
代碼如下
第一次,我們都對這種可能性感到驚訝和困惑。 我們通常不會在標識列中插入任何值(可以將值插入標識列)。 標識值由SQL Server本身維護。 我們的核心團隊成員之一開始調查此問題並找到瞭解決方案。 現在,我想詳細介紹一下我的同事發現的問題和解決方案。
如何重現?
您需要設置SQL Server 2012並創建測試資料庫。 然後創建一個帶有自動標識列的表:
create table MyTestTable(Id int Identity(1,1), Name varchar(255));
然後插入2行數據
insert into MyTestTable(Name) values ('Mr.Tom'); insert into MyTestTable(Name) values ('Mr.Jackson');
然後查看結果
SELECT Id, Name FROM MyTestTable;
結果是預期的。 現在,只需重新啟動SQL Server服務即可。 您可以通過多種方式進行操作。 我們是從SQL Server Management Studio完成的。
重啟之後,我們向剛纔的表格再插入2條數據
insert into MyTestTable(Name) values ('Mr.Tom2'); insert into MyTestTable(Name) values ('Mr.Jackson2');
查看結果
SELECT Id, Name FROM MyTestTable;
現在你看到重啟SQL Server 2012 之後的結果,它的自增列的值從1002開始了。 也就是跳躍了 1000。之前說過,如果我們自增列的數據類型是 長整型(bigint)的話,它的跳躍值就將會是 10000。
真的是個Bug嗎?
Microsoft宣稱它是功能而不是錯誤,並且在許多情況下會有所幫助。 但是在我們的情況下,這是不可接受的,因為該數字會顯示給客戶端,並且客戶端會驚訝地看到跳轉後的新數字,而新數字取決於重新啟動SQL Server的次數。 如果客戶端看不到它,則可以接受,以便在內部使用該號碼。
解決方案
如果我們對微軟提供的這個 “功能” 不感興趣,我們可以通過兩種途徑來關閉它。
1. 使用序列 (Sequence)
2. 為SQL Server 註冊啟動參數 -t272
使用序列
首先,我們需要移除表格的自增列。然後創建一個不帶緩存功能的序列,根據此序列插入數值。 下麵是示例代碼
CREATE SEQUENCE Id_Sequence AS INT START WITH 1 INCREMENT BY 1 MINVALUE 0 NO MAXVALUE NO CACHE insert into MyTestTable values(NEXT VALUE FOR Id_Sequence, 'Mr.Tom'); insert into MyTestTable values(NEXT VALUE FOR Id_Sequence, 'Mr.Jackson');
註冊啟動參數 -t272
打開SQL Server配置管理器。 選擇 SQL Server 2012 實例,右鍵, 選擇屬性菜單。在彈出的視窗中找到啟動參數,然後註冊 -t272。 完成之後重啟下圖中的SQL Server(SQLSERVER2012), 之後進行bug重現的操作,驗證問題是否已解決。
如果太多的表包含資料庫的標識列,並且所有表都包含現有值,則最好使用解決方案2。因為這是一個非常簡單的解決方案,並且其範圍是伺服器明智的。 這意味著,如果在此處添加SQL Server 2012參數-t272,則會影響在那裡的所有資料庫。 如果要創建新資料庫,並且需要自動生成的數字欄位,則可以使用解決方案1,這意味著對列使用序列值而不是自動標識值。 您可以在網上找到很多文章,有關何時使用序列和彼此的優缺點時將使用自動標識列。 希望您閱讀所有這些內容並做出適當的決定。
相關鏈接:https://www.codeproject.com/Tips/668042/SQL-Server-2012-Auto-Identity-column-Value-Jump-Is