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

发布于 2024-07-25 16:02:58 字数 1139 浏览 6 评论 0原文

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

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

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

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

在 C# 中:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

请注意,IsolationLevel Snapshot 与 ReadComfilled Snapshot 不同,我们也尝试过后者,但目前尚未使用。

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

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

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

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

I'm part of a team building an ADO.NET based web-site. We sometimes have several developers and an automated testing tool working simultaneously a development copy of the database.

We use snapshot isolation level, which, to the best of my knowledge, uses optimistic concurrency: rather than locking, it hopes for the best and throws an exception if you try to commit a transaction if the affected rows have been altered by another party during the transaction.

To use snapshot isolation level we use:

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

and in C#:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

Note that IsolationLevel Snapshot isn't the same as ReadCommitted Snapshot, which we've also tried, but are not currently using.

When one of the developers enters debug mode and pauses the .NET app, they will hold a connection with an active transaction while debugging. Now, I'd expect this not to be a problem - after all, all transactions are using snapshot isolation level, so while one transaction is paused, other transactions should be able to proceed normally since the paused transaction isn't holding any locks. Of course, when the paused transaction completes, it is likely to detect a conflict; but that's acceptable so long as other developers and the automated tests can proceed unhindered.

However, in practice, when one person halts a transaction while debugging, all other DB users attempting to access the same rows are blocked despite using snapshot isolation level.

Does anybody know why this occurs, and/or how I can achieve true optimistic (non-blocking) concurrency?

The resolution (an unfortunate one for me): Remus Rusanu noted that writers always block other writers; this is backed up by MSDN - it doesn't quite come out and say so, but only ever mentions avoiding reader-writer locks. In short, the behavior I want isn't implemented in SQL Server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

染年凉城似染瑾 2024-08-01 16:02:59

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

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

SNAPSHOT isolation level affects, like all isolation levels, only reads. Writes are still blocking each other. If you believe that what you see are read blocks, then you should investigate further and check out the resource types and resource names on which blocking occurs (wait_type and wait_resource in sys.dm_exec_requests).

I wouldn't advise in making code changes in order to support a scenario that involves developers staring at debugger for minutes on end. If you believe that this scenario can repeat in production (ie. client hangs) then is a different story. To achieve what you want you must minimize writes and perform all writes at the end of transaction, in one single call that commits before return. This way no client can hold X locks for a long time (cannot hang while holding X locks). In practice this is pretty hard to pull off and requires a lot of discipline on the part of developers in how they write the data access code.

帝王念 2024-08-01 16:02:59

当一名开发人员暂停事务时,您是否看过锁? 另外,仅仅打开快照隔离级别并没有太大效果。 您是否已将 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

Raj

Have you looked at the locks when one developer pauses the transaction? Also, just turning on snapshot isolation level does not have much effect. Have you set ALLOW_SNAPSHOT_ISOLATION ON?

Here are the steps:

ALTER DATABASE <databasename>
SET READ_COMMITTED_SNAPSHOT ON;
GO

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

After the database has been enabled for snapshot isolation, developers and users must then request that their transactions be run in this snapshot mode. This must be done before starting a transaction, either by a client-side directive on the ADO.NET transaction object or within their Transact-SQL query by using the following statement:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

Raj

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文