Grz*_*zes 6 sql deadlock transactions isolation-level sql-server-2008
我使用一个包含两个简单查询的小事务: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的死锁,但我担心它们可能会发生.你推荐什么解决方案?
| 归档时间: |
|
| 查看次数: |
7149 次 |
| 最近记录: |