7

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

我们使用快照隔离级别,据我所知,它使用乐观并发:而不是锁定,它希望做到最好,如果在受影响的行已被另一方更改期间尝试提交事务,则会引发异常交易。

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

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

在 C# 中:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

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

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

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

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

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

4

2 回答 2

8

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

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

于 2009-06-25T14:27:09.127 回答
2

当一位开发人员暂停事务时,您是否查看过锁?另外,仅仅开启快照隔离级别并没有太大的影响。您是否已将 ALLOW_SNAPSHOT_ISOLATION 设置为 ON?

以下是步骤:

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

拉吉

于 2009-06-25T14:24:22.593 回答