[英]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.