锁定事务 (SQL Server + EF5)
Posted
技术标签:
【中文标题】锁定事务 (SQL Server + EF5)【英文标题】:Locking transactions (SQL Server + EF5) 【发布时间】:2019-06-30 06:37:04 【问题描述】:我正在尝试使用 .NET 4.5、EF5(具有二级缓存和延迟加载的导航属性)和 SQL Server 2014 调试 ASP.NET 应用程序中的性能问题。我们在SQL 服务器。当我查看锁定事务时,它们包含一个非常快速的 UPDATE,然后是一个非常大的 SELECT。 UPDATE 表面上是必要的,但我很困惑为什么 SELECT 在同一个事务中运行(以及为什么要选择任何东西)。根本问题是 UPDATE 语句中引用的表在 SELECT 语句期间被锁定。
我们使用存储库模式从数据库中获取数据,并使用 DbContext.SaveChanges() 来提交更改。我无法弄清楚 EF 怎么可能产生一个同时存在写入和读取的事务,并且当我尝试搜索 Google 时没有得到相关结果。
我们有许多进入系统的接口,还有几个在数据库上工作的控制台应用程序,但它们都经过相同的 .NET 和 EF 设置/版本。
我认为它必须通过 SaveChanges,因为这是(AFAIK)唯一一次将内容写入数据库。
这里有没有人暗示这些锁定事务是如何产生的?
【问题讨论】:
在 SaveChanges 中预期更新后选择。但是由 SaveChanges() 引起的更新应该获得足够的锁以允许后续的 SELECT 执行而不会阻塞。因此,您需要诊断 SELECT 以找出它们长时间运行的原因。例如,如果您缺少主键索引,则 SELECT 可能需要扫描。 【参考方案1】:根本问题是 UPDATE 中引用的表 语句在 SELECT 语句期间被锁定。
答案就在你的问题中:
SELECT 在同一个事务中运行
X
锁始终保持到transaction
结束,即直到它提交或回滚。因此,如果在您的快速update
之后有一个很长的select
,则锁定在您的表格中的所有update
都将保持锁定状态,直到您的select
结束。
如果您的业务规则允许,您可以将update
和select
分开,您可以在更新的表上添加适当的index
以仅锁定部分行而不是整个表,或者您可以优化您的@987654330 @ 执行得更快。
【讨论】:
我意识到锁定的原因是语句被分组在一个事务中,将它们分开可以解决问题。问题是我不知道为什么或如何将它们分组。使用存储库模式和 SaveChanges 我不知道 EF 如何在同一事务中生成具有读取和写入的事务,因此,我很难找到产生问题的代码。 我不知道如何帮助您处理 EF,但您仍然可以创建索引以减少更新表时的锁定。我怀疑你有一个堆,否则整个表不应该被锁定 SaveChanges() 调用不仅会插入/更新/删除上下文 ChangeTracker 中引用的所有实体,而且会在调用提交后选择所有条目以确保正确更新所有内容(基于定义的并发令牌)。所有这些都发生在 DbConnection 中使用的环境事务中,或者,如果不存在,则发生在 EF 为封装 SaveChanges() 调用而创建的单独事务中。以上是关于锁定事务 (SQL Server + EF5)的主要内容,如果未能解决你的问题,请参考以下文章