MS SQL Identity 欄位數值跳號問題探討

MS SQL Identity 欄位數值跳號問題探討

關於MS SQL Identity欄位數值跳號問題之前就有發現,當時微軟MVP Terry有詢問微軟這個問題。

 

微軟給的回覆是Identity欄位不保證連號,在某些情況下會造成跳號問題。而近期在FB也有社團朋

 

友提出一樣的問題,因此自己做了一下LAB並記錄一下。

 

 

目前我知道會造成跳號的情況如下(如果您知道還有其他狀況會造成跳號,歡迎分享給我)

 

1.交易已取號,但後來Rollback

 

2.重啟SQL服務。

 

3.Restore資料庫。

 

 

而這一次我測試了4SQL版本(SQL2008R2SQL2012SQL2014SQL2016CTP2),看看不同

 

版本是否有差異性。

 

 

情境一 : 交易已取號,但後來Rollback

 

測試語法如下

Use [master]
GO
Create Database RockDB;
GO
Use [RockDB]
GO
Create Table Tb(Id INT Identity,Name Char(4));
GO
Insert Into Tb Values('Rock');
GO
Begin Tran
Insert Into Tb Values('Rock');
Rollback
GO
Insert Into Tb Values('Rock');
GO
Select *,left(@@version,25) AS DbVersion From Tb;
GO

 

測試結果 : 我們在4個版本的SQL上執行上面的語法,結果如下。我們透過測試結果可以知道,

 

交易的Rollback4SQL版本都會造成跳號。

 

clip_image002

clip_image004

clip_image006

clip_image008

 

 

 

 

情境二 : 重啟SQL服務。測試方法如下

 

(1)我們先執行下面語法,產生相關表格並塞入資料

 

Use [master]
GO
Create Database RockDB;
GO
Use [RockDB]
GO
Create Table Tb(Id INT Identity,Name Char(4));
GO
Insert Into Tb Values('Rock');
GO
Insert Into Tb Values('Rock');
GO

 

 

(2)如下圖所示,重啟SQL服務

 

clip_image010

 

 

(3)完成重啟服務後再次塞入資料到資料表中

 

clip_image012

 

 

 

 

測試結果 : 上述為測試步驟,結果如下。我們可以發現SQL2012SQL服務重啟後會造成跳號,

 

而且一次就增加1000號。這是SQL2012的已知問題,已在SQL2014SQL2016CTP2就修正了

 

這一個問題。

 

clip_image014

clip_image016

clip_image018

clip_image020

 

 

 

 

情境三 : 還原資料庫。

 

執行語法如下

 

Use [master]
GO
Create Database RockDB;
GO
Use [RockDB]
GO
Create Table Tb(Id INT Identity,Name Char(4));
GO
Insert Into Tb Values('Rock');
GO
Backup Database RockDB To Disk=N'E:\SQLBak\RockDB.bak'
GO
Insert Into Tb Values('Rock');
GO
Backup Log RockDB To Disk=N'E:\SQLBak\RockDB.trn'
GO
Insert Into Tb Values('Rock');
GO
Use [master]
Go
Backup Log RockDB To Disk=N'E:\SQLBak\RockDB_Taillog.trn' With NoRecovery;
Restore Database RockDB From Disk=N'E:\SQLBak\RockDB.bak' With NoRecovery;
Restore Log RockDB From Disk=N'E:\SQLBak\RockDB.trn' With Recovery;
GO
Use [RockDB]
GO
Insert Into Tb Values('Rock');
GO
Select *,left(@@version,25) AS DbVersion From Tb;
GO
 

 

 

測試結果 : 上述為測試步驟,結果如下。我們可以發現只有SQL2008R2在還原資料庫後不

 

會有跳號情況,在SQL2012 UP版本的SQL,在資料庫還原後再塞入資料都會有跳1000

 

的情況產生。

 

clip_image022

clip_image024

clip_image026

clip_image028

 

 

 

 

完成上述所有測試後,簡易的列表一下

 

 

SQL2008R2

SQL2012

SQL2014

SQL2016CTP2

交易Rollback

跳號

跳號

跳號

跳號

重啟SQL服務

 

跳號

 

 

還原資料庫

 

跳號

跳號

跳號

 

 

 

 

 

 

 

 

 

 

 

 

 

解決方案 : SQL2012 UP版本在還原資料庫後都會有跳號情況,而SQL2012連服務重啟都

 

會造成跳號。網路上有很多相關文章都會提到這個解決方案,那就是加入SQL服務啟動參

 

–t272,如下圖所示。

 

clip_image030

 

 

加入此一參數後再重啟SQL後會有甚麼樣變化呢? 以下是我找到的說明

 

Trace Flag : 272

Function: Generates a log record per identity increment.

Can be users to convert SQL 2012 back to old style Identity behavior

 

 

加入啟動參數272後,SQL會採用舊版的Identity運作模式,會在交易紀錄檔中記錄每筆取號的紀錄。

 

然而這樣的動作對於SQL是會有額外的負擔,但我想SQL2008R2也是採用相同方式運作,所以應該

 

不會有明顯的效能影響吧。

 

 

 

下圖為沒有啟動-t272參數時交易紀錄的內容,如紅色圈選處可以看見寫入一筆紀錄進Table

 

會有3筆交易紀錄。

 

clip_image032

 

 

 

而當我們啟動-t272參數後,交易紀錄的內容有了改變,如紅色圈選處可以看見加入啟動參數後,

 

寫入一筆紀錄進Table,會有4筆交易紀錄,而多出來的那一筆就是用來記錄Identity的取號紀錄。

 

clip_image034

我是ROCK

rockchang@mails.fju.edu.tw