【问题标题】:Why isn't this transaction isolated?为什么这个事务没有被隔离?
【发布时间】:2011-07-19 14:23:05
【问题描述】:

我有一些方法——调用 SQL Server 和一些业务逻辑来生成唯一值。这些方法都包含在父方法中:

GenerateUniqueValue()
{
  //1. Call to db for last value
  //2. Business logic to create new value
  //3. Update db with new value created
}

我希望对 GenerateUniqueValue 的调用被隔离,即 - 当两个客户端同时调用它时,第二个客户端必须等待第一个客户端完成。

最初,我将服务设为单例;但是,我必须预见到可能包括负载平衡的未来变化,所以我相信单例方法已经过时了。接下来我决定通过装饰我的服务来尝试事务方法:

[ServiceBehavior(TransactionIsolationLevel = IsolationLevel.Serializable, TransactionTimeout = "00:00:30")]

还有我的 GenerateUniqueValue:

[OperationBehavior(TransactionScopeRequired = true)]

问题是同时命中服务方法的测试导致错误:

“System.ServiceModel.ProtocolException:执行此方法调用的事务被异步中止。”

这是我的客户端测试代码:

private static void Main(string[] args)
    {

        List<Client> clients = new List<Client>();
        for (int i = 1; i < 20; i++)
        {
            clients.Add(new Client());
        }

        foreach (var client in clients)
        {
            Thread thread = new Thread(new ThreadStart(client.GenerateUniqueValue));
            thread.Start();
        }

        Console.ReadLine();
    }

如果假设事务是隔离的,为什么多个线程调用该方法会发生冲突?

【问题讨论】:

    标签: wcf concurrency transactions


    【解决方案1】:

    事务用于将多个动作视为单个原子动作。所以如果你想让第二个线程等待第一个线程完成,你必须处理并发而不是事务。

    尝试将 System.ServiceModel.ServiceBehaviorAttribute.ConcurrencyMode 属性与 Single 或 Reentrant 并发模式一起使用。我想这就是你所期待的。

    [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
    

    我猜你得到了异常,因为 IsolationLevel.Serializable 将使第二个线程能够访问易失性数据,但不会让它改变它。您可能正在执行此隔离级别不允许的一些更改操作。

    【讨论】:

      猜你喜欢
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多