2011-04-14 37 views
2

我們必須自己修改數據庫並管理IDENTITY列(而不是依賴auto-inc字段)。SQL Server SCOPE_IDENTITY() - 線程安全

我們的解決方案是有一個「發電機」表,它有一個自動增加字段。我們插入到這張表中,然後讀取SCOPE_IDENTITY值以獲得我們的新ID,例如

insert into NewIDEntity 
     (CreationDate) 
     select 
     GetDate() 

select @EntityID = SCOPE_IDENTITY() 

我們主要關心的是以下情況:

•事務1插入到NEWID和接收101作爲新的ID插入到實體表。
•在它可以提交之前,將事務2插入到NEWID中,並且還接收101作爲新ID(這是因爲SCOPE_IDENTITY()將在當前範圍的上下文中返回ID.原始行尚未提交,所以我們預計值爲101)

•事務1提交併寫入該行。
•事務2嘗試提交,但101已經寫入並導致主鍵違例並中止事務。

但是在運行這個時候,似乎SCOPE_IDENTITY()是由SQL Server處理的,即使在READ UNCOMMITTED隔離級別下運行,我們也沒有衝突。

這是好的還是有我們一直無法找到的陷阱?

感謝 鄧肯

+0

應該工作(單行插入),但你希望從中獲得什麼好處? – 2011-04-14 16:40:32

+1

爲什麼你必須這樣做,即。 「我們必須修改我們的數據庫並自己管理IDENTITY列(而不是依靠auto-inc字段)」? – 2011-04-14 16:43:49

+0

這是一個非常具體的場景,涉及不同的數據庫和移動數據 - 不是一個有利的解決方案,只需要知道它是否可能!謝謝 – Duncan 2011-04-14 17:32:26

回答

7

身份生成本質上是交易 - 該ID計數器總是碰到儘快產生一個ID,不只是當事務提交的任何範圍之外。這導致身份序列在事務回滾時存在差距,但這是因爲它確保了您描述的那種情況的安全性。

1

我同意Araqnid的回答,但只是作爲一個更好的觀點,除非你想保留生成的id的歷史記錄,那麼你也可以在完成後刪除它們。我們還有一個以特定方式生成ID的業務需求(以其他值作爲前綴),我這樣做的方式是通過一個僅包含身份字段的表。然後我的代碼如下所示:

/* 
* There is no "user data" being added to the table, so we just use 
* "Default Values". 
*/ 
Insert Into dbo.MasterIds Default Values 

Set @MasterId = Scope_Identity() 

/* 
* We don't keep just serial numbers on this table. Now that we have 
* the new MasterId delete it from the table. 
*/ 
Delete From dbo.MasterIds 
Where MasterId = @MasterId 

Select @MasterId As MasterId 

希望有所幫助。