使用IsolationLevel.Snapshot,但数据库仍处于锁定状态
技术问答
257 人阅读
|
0 人回复
|
2023-09-14
|
我是构建基于ADO.NET的网站的团队的一部分。有时我们有几个开发人员和一个自动化测试工具,它们同时在开发数据库的副本。
" R2 }9 M; o1 H! e/ Z$ b# P我们使用快照隔离级别,据我所知,它使用乐观并发性:它不是锁定,而是希望达到最佳状态,并且如果在受影响的行已在另一方更改期间尝试提交事务,则它会抛出异常交易。/ Y5 R! Q% }( |
要使用快照隔离级别,我们使用:
% w- R! T2 I1 QALTER DATABASE . f5 b% p8 N8 h) i+ J0 U
SET ALLOW_SNAPSHOT_ISOLATION ON;3 R$ ]7 c( O: d8 T3 y
并在C#中:
; I: Y& e) ~; l( k# p( xTransaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);+ j9 B% u. n% p$ O8 r
请注意,IsolationLevel Snapshot与ReadCommitted Snapshot不同,我们也曾尝试使用它,但当前未使用它。/ f) w, J+ Y% m/ x4 h
当开发人员之一进入调试模式并暂停.NET应用程序时,他们将在调试时保持与活动事务的连接。现在,我希望这不会成为问题-
4 x0 v. `) k+ X: I毕竟,所有事务都使用快照隔离级别,因此,在暂停一个事务的同时,其他事务应该能够正常进行,因为暂停的事务没有任何锁。当然,当暂停的事务完成时,很可能会检测到冲突。但这是可以接受的,只要其他开发人员和自动化测试可以不受阻碍地进行即可。7 g% H, i; D f- ~6 K* a! M3 ?
但是,实际上,当一个人在调试时暂停事务时,尽管使用快照隔离级别,所有试图访问同一行的其他DB用户也会被阻止。7 D2 r4 N3 a" ^) t: g* i- \
有谁知道为什么会这样,和/或我如何实现真正的乐观(非阻塞)并发?5 ~! ]% H0 t) a1 |* `* E
5 i, D! j0 m) L) I解决方案:
7 o/ p! F2 v, g4 P9 S3 v, g
' _8 G" `* a' }2 t+ \' u: ?9 E7 W- Y) K% c! U0 d8 j
" t. S( d5 {/ b5 z3 t4 e
像所有隔离级别一样,SNAPSHOT隔离级别只会影响读取。写入仍然相互阻塞。如果您认为看到的是读取块,则应该进一步调查并检查发生阻塞的资源类型和资源名称(sys.dm_exec_requests中的wait_type和wait_resource )。2 {- \" X A' Y* W5 n$ d
我不建议进行代码更改以支持涉及开发人员最后几分钟盯着调试器的情况。如果您认为这种情况会在生产中重复出现(即客户挂起),那就是另一回事了。要实现所需的功能,必须在事务返回之前一次提交并在返回之前提交的事务中,最小化写操作并在事务结束时执行所有写操作。这样,任何客户端都无法长时间持有X锁(持有X锁时无法挂起)。在实践中,这很难实现,并且要求开发人员在编写数据访问代码的方式方面进行大量训练。 |
|
|
|
|
|