锁定事务 (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 结束。

如果您的业务规则允许,您可以将updateselect 分开,您可以在更新的表上添加适当的index 以仅锁定部分行而不是整个表,或者您可以优化您的@987654330 @ 执行得更快。

【讨论】:

我意识到锁定的原因是语句被分组在一个事务中,将它们分开可以解决问题。问题是我不知道为什么或如何将它们分组。使用存储库模式和 SaveChanges 我不知道 EF 如何在同一事务中生成具有读取和写入的事务,因此,我很难找到产生问题的代码。 我不知道如何帮助您处理 EF,但您仍然可以创建索引以减少更新表时的锁定。我怀疑你有一个堆,否则整个表不应该被锁定 SaveChanges() 调用不仅会插入/更新/删除上下文 ChangeTracker 中引用的所有实体,而且会在调用提交后选择所有条目以确保正确更新所有内容(基于定义的并发令牌)。所有这些都发生在 DbConnection 中使用的环境事务中,或者,如果不存在,则发生在 EF 为封装 SaveChanges() 调用而创建的单独事务中。

以上是关于锁定事务 (SQL Server + EF5)的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server学习笔记事务锁定阻塞死锁

SQL Server 的锁定和阻塞

SQL Server 触发器插入导致锁定直到提交

SQL SERVER的锁机制——概述(锁的种类与范围)

SQL Server 事务/并发混乱 - 你必须总是使用表提示吗?

事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。在 sql server 2014 中