[英]What is the meaning of Isolation for a transaction that propagates from WCF client to WCF service?
這個問題分為三個部分:
可以從這里下載代碼
假定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();
}
}
}
還假設:
同時運行兩個客戶端進程。
預期結果是兩個客戶退出后的帳戶余額應比兩個客戶都啟動前的帳戶余額大20000。
兩個客戶端退出后帳戶的余額在10000到20000之間。在某些情況下,其中一個客戶端由於以下錯誤而中止:
事務(進程ID)已與另一個進程在鎖定資源上發生死鎖,並已被選擇為死鎖受害者
每個客戶端上的TransactionScope范圍內包含的操作並未與另一個客戶端上的整體串聯運行。 來自兩個事務的讀取和寫入混合在一起,並且某些增量丟失了。
問題 :“如果我對隔離的解釋不正確,那么正確的解釋是什么?”。
答 :問題中的錯誤假設是,如果兩個事務不能同時運行,則一個事務將等待另一個事務完成然后繼續。 這是不正確的。 實際上,可序列化事務是隔離的,不會並行運行,但這並不意味着一個將等待另一個。 事務隔離與持有互斥鎖以獨立執行一組操作不同。
問題 :“以及如何修改測試以證明使用序列化事務與完全不使用事務之間的區別”
答 :以下代碼片段將演示如何使用事務來確保按預期進行增量。
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.