为啥实体框架在保存时锁定表?
Posted
技术标签:
【中文标题】为啥实体框架在保存时锁定表?【英文标题】:Why Entity Framework locks tables on save?为什么实体框架在保存时锁定表? 【发布时间】:2015-07-06 08:08:04 【问题描述】:我有一个事务将大量数据(超过 5000 多条记录)插入 3 个表(因此需要一段时间),这没关系,但我注意到一些令人不安的事情。在此过程中,所有 3 个表似乎都被锁定了。
插入交易:
using(var db = new MyEntities())
using (var tr = db.Database.BeginTransaction())
// blah, blah, a lot of entities to create, **some custom SQL, bulk inserts** etc.
db.SaveChanges();
tr.Commit();
无论是 EF 还是原始 SQL 查询,我都无法从表中读取数据。但是使用 (NOLOCK) 选择有效:
SELECT * FROM Table1 WITH (NOLOCK)
首先我想知道实际发生了什么?是否只是“自然”行为和表被锁定,或者可能是锁定升级或其他原因。
其次,是否可以禁用插入事务级别的锁?还是我必须在所有 SELECT 查询中添加“WITH (NOLOCK)”?
第三,是否可以让 SELECT 查询在保存期间返回数据,但仅来自已提交事务的记录(例如,我的插入事务已经添加了 2000 条记录,3000 条待处理,我进行了一个选择查询,它返回除了那些之外的所有记录2000,尚未提交)。
【问题讨论】:
你在那里明确地使用了一个事务,那么为什么要读取提交的数据,你必须等到事务被提交才会让你感到惊讶? 【参考方案1】:表未锁定。正在插入的特定记录被锁定。您注意到阻塞是因为您在提交之前尝试读取这些新插入的行。
在您的数据库中启用已提交读快照。
ALTER DATABASE <yourdb> SET READ_COMMITTED_SNAPSHOT ON;
对于那些想要学习的人来说,lock escalation、missing indexes causing scans 和cost of row level isolation 有更多详细信息。
【讨论】:
【参考方案2】:-
是的,写数据的时候加锁就可以了。此外,系统可能会在需要时升级锁,因此您最终可能会得到比您乍一看更多的锁
您不想禁用锁,但有tricks(索引覆盖更多列)可能有助于缓解选择时的锁定问题。也仅在必要时使用
NOLOCK
提示;有人打电话给bad habit to kick。看看TRANSACTION ISOLATION LEVEL,它在以更可控的方式处理此类问题时可能很有用。
是的,这是可能的,但这不是您的情况。您有一个在最后提交的大型事务,因此您肯定可以读取所有已提交的行,但由于所有行都在批处理结束时提交,您必须等待整个批处理完成才能读取它们。李>
【讨论】:
以上是关于为啥实体框架在保存时锁定表?的主要内容,如果未能解决你的问题,请参考以下文章