代码之家  ›  专栏  ›  技术社区  ›  Eamon Nerbonne

正在使用IsolationLevel.Snapshot,但数据库仍处于锁定状态

  •  7
  • Eamon Nerbonne  · 技术社区  · 15 年前

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

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

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

    ALTER DATABASE <database name>
    SET ALLOW_SNAPSHOT_ISOLATION ON;
    

    Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);
    

    请注意,IsolationLevel Snapshot与ReadCommitted Snapshot不同,我们也尝试了ReadCommitted Snapshot,但目前未使用它。

    然而,在实践中,当一个人在调试时停止事务时,尽管使用了快照隔离级别,尝试访问相同行的所有其他DB用户都会被阻止。

    有人知道为什么会发生这种情况,和/或我如何实现真正的乐观(非阻塞)并发吗?

    决议(对我来说是一个不幸的决议) Remus Rusanu 注意到作者总是阻止其他作者;这一点得到了以下方面的支持: MSDN

    2 回复  |  直到 7 年前
        1
  •  8
  •   Remus Rusanu    15 年前

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

    我不建议为了支持开发人员连续几分钟盯着调试器的场景而修改代码。如果您认为这种情况可以在生产中重复(即客户端挂起),那么情况就不同了。为了实现您想要的,您必须最小化写入,并在事务结束时在一个在返回之前提交的调用中执行所有写入。这样,任何客户端都不能长时间持有X锁(不能在持有X锁时挂起)。在实践中,这很难实现,并且需要开发人员在如何编写数据访问代码方面遵守很多规则。

        2
  •  2
  •   Raj    15 年前

    以下是步骤:

    ALTER DATABASE <databasename>
    SET READ_COMMITTED_SNAPSHOT ON;
    GO
    
    ALTER DATABASE <database name>
    SET ALLOW_SNAPSHOT_ISOLATION ON;
    GO
    

    启用数据库进行快照隔离后,开发人员和用户必须请求在此快照模式下运行其事务。在启动事务之前,必须通过ADO.NET事务对象上的客户端指令或使用以下语句在其Transact-SQL查询中执行此操作:

    SET TRANSACTION ISOLATION LEVEL SNAPSHOT
    

    拉吉