c# - LINQ2SQL 事务性能

标签 c# linq-to-sql

我在 LINQ2SQL 和事务方面遇到了重大性能问题。我的代码使用 IDE 生成的 LINQ2SQL 代码执行以下操作:

运行存储过程检查现有记录 如果记录不存在则创建 运行一个存储过程,将其自己的代码包装在事务中

当我在没有事务范围的情况下运行代码时,每秒迭代 20 次。一旦我将代码包装在事务范围内,它就会下降到每秒 3-4 次迭代。我不明白为什么在顶层添加事务会降低性能这么多。请帮忙?

带有事务的伪存储过程:

begin transaction
update some_table_1;
insert into some_table_2;
commit transaction;

select some, return, values

没有事务的伪 LINQ 代码:

var db = new SomeDbContext();
var exists = db.RecordExists(some arguments);

if (!exists) {
    var record = new SomeRecord 
    {
        // Assign property values
    };

    db.RecordsTable.InsertOnSubmit(record);
    db.SubmitChanges();

    var result = db.SomeStoredProcWithTransactions();
}

带有事务的伪 LINQ 代码:

var db = new SomeDbContext();
var exists = db.RecordExists(some arguments);

if (!exists) {
    using (var ts = new TransactionScope()) 
    {
        var record = new SomeRecord 
        {
            // Assign property values
        };

        db.RecordsTable.InsertOnSubmit(record);
        db.SubmitChanges();

        var result = db.SomeStoredProcWithTransactions();
        ts.Complete();
    }
}

我知道事务没有升级到 DTC,因为我已禁用 DTC。 SQL Profiler 显示,在启用 transactionscope 的情况下,一些查询需要更长的时间,但我不确定为什么。所涉及的查询的生命周期非常短暂,并且我已经验证了正在使用的索引。我无法确定为什么添加父事务会导致性能下降如此之大。

有什么想法吗?

编辑:

我已将问题追溯到最终存储过程中的以下查询:

if exists 
(
    select * from entries where 
        ProfileID = @ProfileID and 
        Created >= @PeriodStart and 
        Created < @PeriodEnd
) set @Exists = 1;

如果我使用了 with(nolock) ,如下所示,问题就会消失。

if exists 
(
    select * from entries with(nolock) where 
        ProfileID = @ProfileID and 
        Created >= @PeriodStart and 
        Created < @PeriodEnd
) set @Exists = 1;

但是,我担心这样做可能会导致以后出现问题。有什么建议吗?

最佳答案

一旦您获得交易,一件大事就会发生变化 - isolation level 。您的数据库是否存在严重争用?如果是这样:默认情况下,TransactionScope 处于最高的“可序列化”隔离级别,其中涉及读锁、键范围锁等。如果它不能立即获取这些锁,那么它会减慢速度它被阻止了。您可以通过降低事务的隔离级别(通过构造函数)进行调查。例如(但选择您自己的隔离级别):

using(var tran = new TransactionScope(TransactionScopeOption.Required,
    new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot })) {
    // code
    tran.Complete();
}

但是,选择隔离级别...很棘手;可序列化是最安全的(因此是默认值)。您还可以使用诸如 NOLOCKUPDLOCK 之类的粒度提示(但不能通过 LINQ-to-SQL)来帮助控制特定表的锁定。


您还可以调查速度减慢是否是由于尝试与 DTC 对话所致。启用 DTC 并查看是否加速。 LTM 很好,但我之前见过对单个数据库的复合操作升级为 DTC...

关于c# - LINQ2SQL 事务性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/856010/

相关文章:

c# - 如何捕获此 WPF 位图加载异常?

c# - 同时播放三种声音C#

c# - 使用 linq2sql/datacontext 将记录插入数据库

c# - 如何获取正在调用我的方法的类名? [复制]

c# - 是否在扩展方法类中调用扩展方法?

c# - 使用 LINQ-to-SQL 跟踪数据库的外部更改

linq - 将 Linq 与 WCF 结合使用

.net - 如何使用 Linq-to-SQL 只插入新记录?

c# - 没有特定顺序的占位符 (mmddyyyy) 的正则表达式

c# - SQL Server CE 不兼容的数据库版本