簡體   English   中英

從WCF客戶端傳播到WCF服務的事務的隔離是什么意思?

[英]What is the meaning of Isolation for a transaction that propagates from WCF client to WCF service?

這個問題分為三個部分:

  1. 為什么可序列化事務不能自動執行操作?
  2. 假設答案是事務的原子性不能保證其組成操作的原子性(並且只能確保所有操作要么全部成功要么全部失敗),為什么事務的隔離要求不能確保該操作是原子性的? 我已經讀過,可序列化隔離級別可確保事務像串行執行一樣被執行?
  3. 如果我對隔離的解釋不正確,那么什么是正確的解釋?我如何修改測試以證明使用序列化事務與完全不使用事務之間的區別。

最小完整且可驗證的示例

可以從這里下載代碼

假定DataLayer(DAL)是由WCF服務實現的,並且客戶端代碼包括從Main對其操作的調用:

    public void Main(string[] args)
    {
        var dal = new DataLayerServiceClient();

        var accounts = dal.GetAccounts();
        int accountId = accounts.First().AccountId;

        for (int i = 0; i < 10000; i++)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                var account = dal.GetAccountById(accountId);
                account.Balance++;
                dal.Update(account);

                scope.Complete();
            }
        }
    }

還假設:

  1. 客戶端和服務已正確配置為將客戶端事務傳播到服務。 (這是在服務端通過觀察環境事務來驗證的,該事務具有分布式標識符,並且該標識符與客戶端的標識符相同。
  2. 事務的隔離模式(在服務中和在客戶端上)都是可序列化的(通過觀察服務和客戶端上的環境事務的屬性來驗證)

測試說明

同時運行兩個客戶端進程。

預期結果

預期結果是兩個客戶退出后的帳戶余額應比兩個客戶都啟動前的帳戶余額大20000。

實際結果

兩個客戶端退出后帳戶的余額在10000到20000之間。在某些情況下,其中一個客戶端由於以下錯誤而中止:

事務(進程ID)已與另一個進程在鎖定資源上發生死鎖,並已被選擇為死鎖受害者

結論

每個客戶端上的TransactionScope范圍內包含的操作並未與另一個客戶端上的整體串聯運行。 來自兩個事務的讀取和寫入混合在一起,並且某些增量丟失了。

  1. 問題 :“為什么可序列化事務不能自動執行操作”
    :可序列化事務是原子性的,這意味着它的所有操作都將全部成功或全部失敗。 這個例子沒有反駁。
  2. 問題 :“為什么事務的隔離要求不能確保操作是原子性的?
    :兩個可序列化的事務滿足隔離要求,因為它們不會同時運行。 如果兩個嘗試一起運行,則一個將按計划繼續,而另一個將中止。 這正是問題中報告的異常發生的原因。 (“事務(進程ID)與另一個進程在鎖資源上死鎖,並已被選擇為死鎖受害者”)。
  3. 問題 :“如果我對隔離的解釋不正確,那么正確的解釋是什么?”。
    :問題中的錯誤假設是,如果兩個事務不能同時運行,則一個事務將等待另一個事務完成然后繼續。 這是不正確的。 實際上,可序列化事務是隔離的,不會並行運行,但這並不意味着一個將等待另一個。 事務隔離與持有互斥鎖以獨立執行一組操作不同。
    問題 :“以及如何修改測試以證明使用序列化事務與完全不使用事務之間的區別”
    :以下代碼片段將演示如何使用事務來確保按預期進行增量。

      int i = 0; while(i < 10000) { try { using (TransactionScope scope = new TransactionScope()) { var account = dal.GetAccountById(accountId); account.Balance++; dal.Update(account); scope.Complete(); } i++; } catch (Exception ex) { Console.WriteLine($"{ex.Message} : restarting"); } } 

當然,這效率極低,但是可以按預期工作,並演示了事務如何隔離資源管理器上的操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM