我做了一些研究,但没有找到任何解释。所以,如果那里有一个,我很抱歉。
我正在使用TransactionScope处理与SQL Server 2012数据库的交易。我也在使用Entity Framework。
事实是,当我开始一个新事务将插入一条新记录到我的表中时,它会锁定整个表,而不仅仅是那一行。因此,如果我运行 Db.SaveChanges(),而不提交它,并转到管理工作室并尝试从同一个表中获取已提交的数据,它会挂起并返回给我没有数据。
在这种情况下我想要的只是锁定 new 行,而不是整个表。
这可能吗?
提前谢谢。
答案 0 :(得分:2)
使用TransactionScope时要特别注意的一点是,它默认使用Serializable隔离级别,这会导致SQL Server中出现许多锁定问题。 SQL Server中的默认隔离级别为Read Committed,因此您应该考虑在使用TransactionScope的任何事务中使用它。您可以将创建默认TransactionScope的方法分解出来,并始终默认设置为ReadCommitted(请参阅Why is System.Transactions TransactionScope default Isolationlevel Serializable)。还要确保在使用TransactionScope时有using
块,以确保事务处理回滚的事务处理发生错误(http://msdn.microsoft.com/en-us/library/yh598w02.aspx)。
默认情况下,SQL Server使用悲观并发模型,这意味着在处理DML命令(插入,更新,删除)时,它将获取对正在更改的数据的独占锁定,这将阻止其他更新或完成选择直到释放这些锁。释放这些锁的唯一方法是提交或回滚事务。因此,如果您有一个将数据插入表中的事务,并且在插入完成之前运行SELECT * FROM myTable
,则SQL Server将强制您的select等待,直到打开的事务已提交或回滚,然后才返回结果。通常交易应该小而快,你不会注意到一个问题。以下是有关隔离级别和锁定(http://technet.microsoft.com/en-us/library/ms378149.aspx)的更多信息。
在您的情况下,这听起来像是在调试,并且在事务打开的情况下在代码中遇到了断点。出于调试目的,您可以向查询添加一个nolock提示,该提示将显示已提交的数据的结果以及尚未提交的插入。因为使用nolock将返回UN提交的数据,所以在任何生产环境中使用它都要非常小心。以下是带有nolock提示的查询示例。
SELECT * FROM myTable WITH(NOLOCK)
如果您在调试之外继续遇到锁定问题,那么您还可以查看快照隔离(Kendra Little的精彩文章:http://www.brentozar.com/archive/2013/01/implementing-snapshot-or-read-committed-snapshot-isolation-in-sql-server-a-guide/)。使用快照隔离时有一些特殊注意事项,例如tempdb调整。