繁体   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