【发布时间】:2017-01-20 08:49:54
【问题描述】:
在MSSQL 2008 上使用 EF 处理从查询更新的情况时存在性能和锁定问题。于是我把ReadUncommitted事务隔离级别,希望能解决,像这样,
之前
using (MyEntities db = new MyEntities())
{
// large dataset
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
for (var item in data)
item.Flag = 0;
// Probably db lock
db.SaveChanges();
}
之后
using (var scope =
new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
using (MyEntities db = new MyEntities())
{
// large dataset but with NOLOCK
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
for (var item in data)
item.Flag = 0;
// Try avoid db lock
db.SaveChanges();
}
}
我们使用SQL profiler 进行追踪。但是,按顺序获得这些脚本,
(预计第一个脚本未提交读取。)
审核登录
set transaction isolation level read committed
SP:StmtStarting
SELECT
[Extent1].[ContactId] AS [ContactId],
[Extent1].[MemberId] AS [MemberId],
FROM [dbo].[Contact] AS [Extent1]
WHERE [Extent1].[MemberId] = @p__linq__0
审核登录
set transaction isolation level read uncommitted
虽然我可以重新发送此请求并使其正确排序(对于以下请求,将显示 read-uncommitted,相同的 SPID),我想知道为什么它在 read-committed 命令之后发送了 read-uncommitted 命令以及如何使用 EF 和 TransactionScope 进行修复?谢谢。
【问题讨论】:
-
你也可以在分析器中添加事务相关的事件吗? (开始传输、回滚、提交)。想知道是否实际创建了任何交易,如果是,何时创建。
-
能否更详细地指出性能问题? (选择需要太多,其他查询被此查询阻止等)。未提交读取通常是一个糟糕的选择,应该是最后一个选择。
-
您使用哪种 EF 方法? 'myEntities' 是 DbContext 还是 ObjectContext?
-
您应该致电
TransactionScope.Complete()。这应该不会影响您所看到的内容,并且无论如何您都无法回滚SELECT,但这是一件好事。另请注意,如果您不设置隔离级别,您将获得上次应用于池连接的任何事务级别。如果您从不使用隔离级别做任何事情,这将是默认的read committed,否则它可能是任何事情。见here。 -
@Alexei,myEntities 是一个 DbContext。实际上我遇到了更新数据库锁定问题(通过选择更新),因为查询数据集将是 Contact 的一个大结果,并且可以通过未提交的读取来避免,例如使用 (nolock)。
标签: c# sql-server entity-framework-6 transactionscope read-uncommitted