我是构建基于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中实现.
在我的查询中测量性能时,我想出了隔离级别和经过时间之间的依赖关系,这对我来说是令人惊讶的
READUNCOMMITTED - 409024
READCOMMITTED - 368021
REPEATABLEREAD - 358019
SERIALIZABLE - 348019
Run Code Online (Sandbox Code Playgroud)
左列是表提示,右列是经过的时间(以微秒为单位)(sys.dm_exec_query_stats.total_elapsed_time).为什么更好的隔离级别可以提供更好 这是一台开发机器,无论发生什么都没有并发.由于锁定开销较少,我希望READUNCOMMITTED能够被禁止.
更新:我测量了这个
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
Run Code Online (Sandbox Code Playgroud)
发布和Profiler确认没有缓存命中发生.
有人知道一本好书,其中的事务隔离级别用很多示例和建议来解释,在什么情况下使用什么隔离级别?
当我使用时,我以不同的顺序获取行
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Run Code Online (Sandbox Code Playgroud)
在我的存储过程中.
下面是存储过程中定义的查询.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT CaseRateDetailId,AmtPerWeek
FROM CaseRateDetails
WHERE CaseRateInfoId = @CaseRateInfoId
Run Code Online (Sandbox Code Playgroud)
它返回AmtPerWeek,如下所示:
10000,15000,5000,20000,25000,..
Run Code Online (Sandbox Code Playgroud)
当我不使用时运行相同的查询
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Run Code Online (Sandbox Code Playgroud)
声明它以正确的顺序返回行,即 5000,10000,15000,20000,25000,....
我可以在上面的查询中使用AmtPerWeek子句的顺序,但我想知道它的行为是这样的原因吗?为什么改变行的顺序?
对于SQL Server 2008 R2中的SNAPSHOt隔离级别,MSDN ADO.Net文档中提到了以下内容:
修改数据的事务不会阻止读取数据的事务,而读取数据的事务不会阻止写入数据的事务,因为它们通常在SQL Server中的默认READ COMMITTED隔离级别下.
当两个事务都处于SNAPSHOT隔离模式时,没有提到写入是否会阻止写入.所以我的问题如下: 在SNAPSHOT transaction1块中写入是否会写入另一个SNAPHOT transaction2中的相同表?
最近更新
在对我的问题进行了大量思考之后,我将得出如下段所述的结论.希望其他人可以对此有所了解.
没有关系数据库,写入不会阻止写入.换句话说,写入将始终阻止写入.写入包括INSERT或UPDATE或DELETE等语句.无论您使用哪种隔离级别都是如此,因为当数据库中发生多次写入时,所有关系数据库都需要实现数据一致性.当然,同时写入需要是冲突的(如插入同一个表或更新相同的行),以便发生阻塞.
我使用一个包含两个简单查询的小事务:select和update:
SELECT * FROM XYZ WHERE ABC = DEF
Run Code Online (Sandbox Code Playgroud)
和
UPDATE XYZ SET ABC = 123
WHERE ABC = DEF
Run Code Online (Sandbox Code Playgroud)
事务通常由两个线程启动,并且取决于隔离级别发生死锁(RepeatableRead,Serialization).两个事务都尝试读取和更新完全相同的行.我想知道为什么会这样.导致死锁的查询顺序是什么?我已经读过一些关于锁(共享,独占)以及每个隔离级别锁定的持续时间,但我仍然不完全理解......
我甚至准备了一个总是导致死锁的简单测试.我查看了SSMS和SQL Server Profiler中的测试结果.我开始第一次查询,然后立即开始第二次.
第一个查询:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT ...
WAITFOR DELAY '00:00:04'
UPDATE ...
COMMIT
Run Code Online (Sandbox Code Playgroud)
第二个查询:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT ...
UPDATE ...
COMMIT
Run Code Online (Sandbox Code Playgroud)
现在我无法向您显示详细的日志,但它看起来不那么像这样(我很可能错过了Lock:死锁等等):
(1) SQL:BatchStarting: First query
(2) SQL:BatchStarting: Second query
(3) Lock:timeout for second query
(4) Lock:timeout for first query
(5) Deadlock graph
Run Code Online (Sandbox Code Playgroud)
如果我理解了锁,在(1)第一个查询采用共享锁(执行SELECT),然后进入休眠状态并保持共享锁直到事务结束.在(2)中,第二个查询也采用共享锁(SELECT),但在同一行上存在共享锁时不能采用独占锁(UPDATE),这会导致Lock:timeout.但我无法解释为什么发生第二次查询的超时.可能我不太了解整个过程.任何人都能给出一个很好的解释吗?
我没有注意到使用ReadCommitted的死锁,但我担心它们可能会发生.你推荐什么解决方案?
In Microsoft SQL Server, I use the READ_COMMITTED_SNAPSHOT ISOLATION
ALTER DATABASE MyDatabase
SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON
Run Code Online (Sandbox Code Playgroud)
In Session 1,update the Principal from 4000 to 5000
BEGIN TRAN
Update MyTable Set Principal=5000 Where InvestorId=10
Run Code Online (Sandbox Code Playgroud)
Now in Session 2, I say
Select Principal from MyTable where InvestorId=10
Run Code Online (Sandbox Code Playgroud)
I get 4000, since the Session 1 Transaction is not committed.
If I do not use the READ_COMMITTED_SNAPSHOT isolation mode, and use
sql oracle snapshot-isolation isolation-level read-committed-snapshot
我一直在寻找明确的有关隔离级别的文档(或并发或范围......我不知道到底该怎么称呼它)在SQL Server中的触发器.
我找到了以下来源,表明我认为是真的(也就是说两个用户,对同一个表执行更新 - 即使是相同的行 - 将会执行独立且隔离的触发器):
第一个问题基本上是我试图找到答案的同一个问题,但给出的答案并未提供任何来源.第二个问题也接近标记,答案是相同的,但同样没有提供任何来源.
有人能指出我可用文档做出相同断言的地方吗?
谢谢!
我正在阅读有关数据库锁定(悲观,乐观)机制的内容,
会话 1:
t1:打开事务:
t2:睡眠(3 秒)
t5:updte 用户集 name='x' 其中 id =1
会话 2:t2:更新用户集 name='y' 其中 id=1
我的疑问是: 1. t5 时会发生什么 2. 它是否与隔离级别有任何关系?如果是,不同隔离级别下的行为是什么。3.数据库(mysql,oracle)只做悲观锁吗?
可重复读定义为
更高的隔离级别,即除了保证读提交级别外,还保证读到的任何数据都不会发生变化,如果事务再次读取相同的数据,会发现之前读到的数据就位,不变,可用阅读。
这似乎与快照隔离非常相似。
可重复读取与快照隔离级别有何不同?
isolation-level ×10
sql ×5
sql-server ×3
database ×2
mysql ×2
transactions ×2
ado.net ×1
deadlock ×1
locking ×1
optimization ×1
oracle ×1
t-sql ×1
triggers ×1