我在LINQ2SQL和事务方面有一个很大的性能问题。我的代码使用IDE生成的LINQ2SQL代码执行以下操作:
运行存储的proc检查现有记录,如果记录不存在,创建记录,运行在事务中包装自己代码的存储proc
当我在没有事务范围的情况下运行代码时,每秒会得到20次迭代。一旦我将代码包装在事务范围内,它就会下降到每秒3-4次迭代。我不明白为什么在顶级添加一个事务会使性能降低这么多。请帮帮忙?
Psuedo使用事务存储proc:
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。sure显示,在启用事务作用域时,有些查询所需的时间要长得多,但我不知道为什么。所涉及的查询非常短,而且我已经使用了我已经验证过的索引。我无法确定为什么父事务的添加会导致如此高的性能。
有什么想法吗?
编辑:
我将问题追溯到最终存储过程中的以下查询:
if exists
(
select * from entries where
ProfileID = @ProfileID and
Created >= @PeriodStart and
Created < @PeriodEnd
) set @Exists = 1;如果我有(Nolock),如下图所示,问题就会消失。
if exists
(
select * from entries with(nolock) where
ProfileID = @ProfileID and
Created >= @PeriodStart and
Created < @PeriodEnd
) set @Exists = 1;然而,我担心这样做可能会在未来造成问题。有什么建议吗?
发布于 2009-05-13 05:32:58
一旦您得到一个事务,就会发生变化的一件大事-- 隔离水平。您的数据库是否处于激烈的争用状态?如果是这样的话:默认情况下,TransactionScope处于最高的“可串行化”隔离级别,这包括读取锁、键范围锁等。如果它不能立即获得这些锁,那么它将在阻塞时减速。您可以通过降低事务的隔离级别(通过构造函数)进行调查。例如(但是选择您自己的隔离级别):
using(var tran = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot })) {
// code
tran.Complete();
}然而,选择一个隔离级别是..。棘手;可序列化是最安全的(因此是默认的)。您还可以使用粒度提示(但不是通过LINQ)(如NOLOCK和UPDLOCK )来帮助控制特定表的锁定。
你也可以调查经济放缓是否是由于试图与直接贸易委员会对话。启用DTC并查看它是否加速。LTM很好,但我以前见过一个数据库的复合操作升级到DTC .
发布于 2009-05-13 04:10:33
您调用的存储过程是否参与环境(父)事务?-这就是问题所在。
存储过程很可能参与环境事务,这导致了程度的提高。有一个这里的MSDN文章讨论它们是如何相互关联的。
从该条中:
“当TransactionScope对象加入现有的环境事务时,除非作用域中止事务,否则处理范围对象可能不会结束事务。如果环境事务是由根范围创建的,则只有当根范围被释放时,才会对事务进行提交。如果事务是手动创建的,则事务在中止或由其创建者提交时结束。”
还有一个关于嵌套事务的严肃的文档,看起来它可以直接应用在MSDN在这里上。
注意:
“如果事务处于活动状态时调用TransProc,则基本上忽略TransProc中的嵌套事务,并根据对外部事务所采取的最终操作提交或回滚其INSERT语句。”
我认为这解释了性能上的差异--本质上是维护父事务的成本。克里斯多夫的建议可能有助于减少间接费用。
https://stackoverflow.com/questions/856010
复制相似问题