1
我有以下表(實體框架這裏藍本,但我的問題無關與EF):這是不可重複讀取的情況嗎?
正如你可以看到,這是一個版本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)是不髒的數據。
- 這也不可重複讀或者,也有在任何交易沒有兩個讀取。
- 也是一樣幻像讀,也有在任何交易沒有兩個查詢。
所以我留下了兩個問題:
- 是我的分析是正確的?
- 需要什麼樣的隔離級別,以避免這種問題?
那麼影響隔離級別還有其他的要求嗎?根據http://en.wikipedia.org/wiki/Isolation_(database_systems),** Serializable **隔離級別意味着我不會得到**髒讀**,**不可重複讀**也沒有**幻影讀**。我怎麼知道** Serializable **阻止我的問題? – cheeesus