2013-08-12 95 views
1

我有以下表(實體框架這裏藍本,但我的問題無關與EF):這是不可重複讀取的情況嗎?

enter image description here

正如你可以看到,這是一個版本Product表。 Id列是主鍵,但組合(EntityId, VersionId)也可能是主鍵。 EntityId表示實體的不同版本之間不變的實體的Id。通過編寫一行IsDeleted = 1刪除實體。

,負責數據處理,存儲過程首先檢查數據操作是好的。例如,UPDATE SP檢查實體是否已被刪除。如果這些檢查都成功,SPS將產生在版本表中的新行,接着是新行中Product表:

(pseudo-code): 

sp_Product_Update: 
(1) IF EXISTS (SELECT Id FROM Product WHERE IsDeleted = 1 AND EntityId = @ProductId) 
     RAISERROR "Entity has already been deleted" 
     RETURN 
(2) INSERT INTO Versions ... 
(3) INSERT INTO Product ... (IsDeleted = 0) 

sp_Product_Delete: 
(1) IF EXISTS (SELECT Id FROM Product WHERE IsDeleted = 1 AND EntityId = @ProductId) 
     RAISERROR "Entity has already been deleted" 
     RETURN 
(2) INSERT INTO Versions ... 
(3) INSERT INTO Product ... (IsDeleted = 1) 

這工作都好。

目前,我分析這個併發問題。想象一下以下併發的場景,其中兩個SP都在同一時間調用同一實體:

Transaction 1       Transaction 2 
sp_Product_Update      sp_Product_Delete 

(1) Check succeeds, entity has not yet been deleted. 

             (1) Same check. 

             (2) INSERT INTO Versions... 
             (3) INSERT INTO Product.. (IsDeleted = 1) 

(2) INSERT INTO Versions... 
(3) INSERT INTO Product ... (IsDeleted = 0) 

正如你所看到的,這種競爭情況會導致數據不一致,即這後談到IsDeleted = 0行一個IsDeleted = 1條目。

所以我們要決定我們需要什麼級別的隔離,以避免這種競爭情況。

  • 這似乎不是成爲一個髒讀,由於在讀出(1)是不髒的數據。
  • 這也不可重複讀或者,也有在任何交易沒有兩個讀取。
  • 也是一樣幻像讀,也有在任何交易沒有兩個查詢。

所以我留下了兩個問題:

  • 是我的分析是正確的?
  • 需要什麼樣的隔離級別,以避免這種問題?

回答

1

您的解決方案需要可序列化的隔離級別,因爲所有命令都需要作爲一個原子操作一起執行。

如果你不使用存儲過程,我會鼓勵使用optimistic locking這是專爲這種情況的高吞吐量。

+0

那麼影響隔離級別還有其他的要求嗎?根據http://en.wikipedia.org/wiki/Isolation_(database_systems),** Serializable **隔離級別意味着我不會得到**髒讀**,**不可重複讀**也沒有**幻影讀**。我怎麼知道** Serializable **阻止我的問題? – cheeesus

相關問題