SQL Server事务锁

时间:2017-09-15 18:48:09

标签: sql-server entity-framework

当我使用创建事务的实体框架执行SQL查询并锁定某个表以对其执行耗时的操作时,当另一个应用程序同时尝试从同一个表读取时会发生什么?

SQL Server是否会等待第一个事务完成并在锁定消失后继续执行,或者它只是返回时出现错误,表明该表无法访问?

3 个答案:

答案 0 :(得分:1)

是的,实体框架在调用SaveChanges时自动创建一个事务,默认隔离级别为Read Committed(实际上它是从提供程序获取的,SQL Server的默认值是Read Committed)。

可在this documentation page内找到更多详情。

为了更改隔离级别,您可以在实例化上下文时禁止EF的上下文使用它自己的事务(contextOwnsConnection: false)。

我的首选替代方法是使用TransactionScope,因为它不需要对实例化上下文的方式进行任何更改,保存更改等。但是,请注意its default isolation level is Serializable(引用的问题和答案)还告诉你如何改变它)

注意:不建议使用长事务,也许您应该查看using bulk operations(或检查this library)以避免由正常更改保存生成的多个插入/更新/删除。

答案 1 :(得分:1)

默认情况下,EF将使用READ COMMITTED SNAPSHOT创建SQL Server数据库。这意味着作者不会阻止读者,读者也不会阻止作者。有关基于行版本的隔离级别的详细信息,请参阅Snapshot Isolation in SQL Server

虽然SaveChanges()在事务中锁定了行,但是尝试读取这些行的其他会话将被重定向到版本存储,并读取这些行的最后已知版本。换句话说,读者可以在任何飞行中交易之前的一致时间点查看每个表格。

如果对现有数据库使用EF,则可能没有配置READ COMMITTED SNAPSHOT,在这种情况下,尝试读取事务锁定的行的读取器将阻塞,直到事务结束。通常这只有几毫秒,除非有大量的事务在运行且读者正在尝试扫描大量行,或者存在运行时间较长的事务。在这种情况下,您应该在将来将数据库移动到READ COMMITTED SNAPSHOT。

答案 2 :(得分:-1)

答案是,这取决于。 SQL可以通过多种方式锁定数据。一般来说,如果您正在进行DML操作(插入,更新,删除),并且您尝试从该表中select,它将阻止select直到DML操作完成。

可以使用with (nolock)set transaction isolation level read uncommmitted覆盖(由您自己承担风险)。执行其中一个基本上允许您的查询读取“当前看起来像什么的数据”,这可能是不完整的,甚至包含在事务完成时不会存在的行。

唯一一次返回错误的方法是,如果你的实际连接超时(这将是你的应用程序连接设置中的某些内容),或者你在桌面上造成了死锁(一个更复杂的主题)。