【问题标题】:Is safe to use TransactionScope in Web Applications?在 Web 应用程序中使用 TransactionScope 是否安全?
【发布时间】:2013-12-16 07:42:30
【问题描述】:

在 Web 应用程序中使用 TransactionScope 时,我遇到了一个很大且随机的问题:

我有一个 Web 应用程序,它有一些使用事务的方法:

public class ProductsService
{
    private readonly ProjectDbContext _db;
    public ProductsService(ProjectDbContext db)
    {
        _db = db;
    }

    public void DelteProduct(Guid product_Id)
    {
        Product product = _db.Products.First(p => p.Id == product_Id);

        using (TransactionScope ts = new TransactionScope())
        {
            // Delete comments
            _db.SaveChanges();

            // Delete subscriptions
            _db.SaveChanges();

            // Delete product
            _db.SaveChanges();

            ts.Complete();
        }
    }
}

在本地测试,没问题。

但是,当我将项目投入生产时,我随机收到SqlExceptionTransaction 错误:

System.Data.SqlClient.SqlExceptionTransaction (Process ID 55) was deadlocked on lock resources with another process and has been chosen as the deadlock victim.
Rerun the transaction.

我认为事务应该在队列中工作,新事务应该等到旧事务被提交,而不是阻塞它们——即使发生错误。

  1. 为什么会出现此错误?
  2. 我应该避免在 Web 应用程序中使用事务吗?
  3. 我用TransactionScope错了吗?

【问题讨论】:

  • 这里为什么需要TransactionScope
  • 这是一个简单的例子。我需要确保所有相关条目都已成功删除并且数据库中没有孤立数据
  • 如果ProjectDbContext 是EF 上下文,那么SaveChanges 本身就是事务性的。您不应该以这种方式使用范围。
  • 我知道这一点,但在删除时我需要按顺序提交更改以避免数据库Reference Keys 异常。这个例子比较简单,通常我也会删除其他条目。
  • > 我需要按顺序提交更改-您应该发布有关此的更多详细信息。我无法想象 EF 的情况,当一个人应该匹配删除序列以从存储中删除条目时。

标签: c# asp.net transactions transactionscope


【解决方案1】:

我认为事务应该在队列中工作,新事务应该等到旧事务被提交,而不是阻塞它们——即使发生错误。

事务队列,但仅当可能。当两个事务相互等待时发生死锁;双方都持有对方所需的资源。有大量文章描述了死锁以及它们如何在数据库中发生。

为什么会出现这个错误?

如果您想查看导致死锁的原因,您可以分析您的数据库并分析死锁图 (https://www.simple-talk.com/sql/learn-sql-server/how-to-track-down-deadlocks-using-sql-server-2005-profiler/)。作为一般说明,我会避免使用 TransactionScope 默认构造函数,因为它将事务级别设置为序列化 (http://blogs.msdn.com/b/dbrowne/archive/2010/05/21/using-new-transactionscope-considered-harmful.aspx)。

来自文章:

在 SQL Server 中 SERIALIZABLE 事务很少有用并且极易发生死锁。换句话说,当默认的 READ COMMITTED 隔离级别不能提供正确的隔离语义时,SERIALIZABLE 很少会更好,并且经常会引入严重的阻塞和死锁问题。


我应该避免在 Web 应用程序中使用事务吗?"

无论如何,不​​。事务应该用于定义原子操作,必须提交的事情应该在一个事务中运行。回想起来,Web 应用程序没有什么特别之处,但是:停止使用默认构造函数。

我用错了TransactionScope?”

正如我上面解释的:是的,避免使用默认构造函数并具体说明您的事务级别; “序列化”永远不是正确答案

【讨论】:

  • > 你到处都在使用悲观锁定——你的观点是基于什么?
  • 我假设这不是他使用带有默认构造函数的 TransactionScope 的唯一地方
  • TransactionScope 默认值如何与并发模式(悲观或乐观)相关?
  • 是的,默认的 TransactionScope ctor 将事务级别设置为“Serialized”,这与悲观锁定相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-28
  • 2013-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-10
  • 2012-07-06
相关资源
最近更新 更多