使用IsolationLevel.Snapshot但DB仍然是锁定的

Eam*_*nne 7 sql sql-server ado.net isolation-level

我是构建基于ADO.NET的网站的团队的一员.我们有时会有几个开发人员和一个自动化测试工具同时处理数据库的开发副本.

我们使用快照隔离级别,据我所知,它使用乐观并发:而不是锁定,如果您尝试提交事务(如果受影响的行已被另一方更改),则希望获得最佳并抛出异常交易.

要使用快照隔离级别,我们使用:

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
Run Code Online (Sandbox Code Playgroud)

在C#中:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);
Run Code Online (Sandbox Code Playgroud)

请注意,IsolationLevel Snapshot与ReadCommitted Snapshot不同,我们也尝试过,但目前还没有使用.

当其中一个开发人员进入调试模式并暂停.NET应用程序时,他们将在调试时与活动事务保持连接.现在,我希望这不是一个问题 - 毕竟,所有事务都使用快照隔离级别,因此当一个事务暂停时,其他事务应该能够正常进行,因为暂停的事务没有持有任何锁.当然,当暂停的事务完成时,它可能会检测到冲突; 但只要其他开发人员和自动化测试可以不受阻碍地进行,这是可以接受的.

但是,实际上,当一个人在调试时暂停事务时,尽管使用了快照隔离级别,但所有其他尝试访问相同行的数据库用户都会被阻止.

有谁知道为什么会这样,和/或我如何才能实现真正的乐观(非阻塞)并发?

决议(对我来说不幸):Remus Rusanu指出作家总是阻止其他作家; 这是由MSDN支持的- 它并没有完全说出来,但只是提到避免读写器锁.简而言之,我想要的行为并没有在SQL Server中实现.

Rem*_*anu 8

与所有隔离级别一样,SNAPSHOT隔离级别仅影响读取.写作仍然相互阻碍.如果您认为所看到的是读取块,那么您应该进一步调查并检查发生阻塞的资源类型和资源名称(sys.dm_exec_requests中的 wait_type和wait_resource ).

我不建议进行代码更改,以支持涉及开发人员在几分钟内盯着调试器的场景.如果您认为这种情况可以在生产中重复(即客户端挂起)那么则是另一回事.要实现您想要的目标,您必须在返回之前提交的单个调用中最小化写入并在事务结束时执行所有写入.这样,没有客户端可以长时间保持X锁(在持有X锁时无法挂起).在实践中,这很难实现,并且开发人员在编写数据访问代码方面需要很多纪律.