【发布时间】:2013-12-25 10:38:32
【问题描述】:
我有一个用 Spring 3.0 编写的应用程序,并使用 SQL Server 2012 Enterprise 作为 RDS。
我一直在我的 DAO 操作中使用@Transactional,在这种特殊情况下
@Transactional
public void removeAll(String token) {
cacheDao.delete(token);
}
public ClassSome getValue(String id) {
return cacheDao.getValue(id);
}
我的删除操作是事务性的,但未指定选择操作。这就是下面出现死锁的原因吗?
最近我在数据库中遇到了死锁。主要是上面这两个操作会死锁。
我不明白一个表上的查询如何相互死锁。这是 DBA 给我的示例死锁列表:
<deadlock-list>
<deadlock victim="process1180f5d498">
<process-list>
<process id="process1180f5d498" taskpriority="0" logused="0" waitresource="OBJECT: 6:1266103551:0 " waittime="2141" ownerId="1748561" transactionname="SELECT" lasttranstarted="2013-12-25T11:24:17.140" XDES="0x117ce7ba40" lockMode="S" schedulerid="30" kpid="4424" status="suspended" spid="87" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2013-12-25T11:24:17.140" lastbatchcompleted="2013-12-25T11:24:17.137" lastattention="1900-01-01T00:00:00.137" clientapp="Microsoft SQL Server JDBC Driver" hostname="xxxx" hostpid="0" loginname="xxxx" isolationlevel="read committed (2)" xactid="1748561" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="74" sqlhandle="0x02000000e0a92205aebcb9dd3f38539312f56b0c41af55990000000000000000000000000000000000000000">
select token, type, value from cache where token=@P0 and type=@P1 </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 varchar(8000),@P1 varchar(8000))select token, type, value from cache where token=@P0 and type=@P1 </inputbuf>
</process>
<process id="process117d375c38" taskpriority="0" logused="0" waitresource="OBJECT: 6:1266103551:29 " waittime="2141" ownerId="1748560" transactionname="implicit_transaction" lasttranstarted="2013-12-25T11:24:17.140" XDES="0xf68c743a8" lockMode="X" schedulerid="64" kpid="9628" status="suspended" spid="96" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2013-12-25T11:24:17.140" lastbatchcompleted="2013-12-25T11:24:17.140" lastattention="1900-01-01T00:00:00.140" clientapp="Microsoft SQL Server JDBC Driver" hostname="xxxx" hostpid="0" loginname="xxx" isolationlevel="read committed (2)" xactid="1748560" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="74" sqlhandle="0x0200000023b477359eec278e4060e11f3a1c194cbed41cc10000000000000000000000000000000000000000">
delete cache where token=@P0 and type=@P1 </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@P0 varchar(8000),@P1 varchar(8000))delete cache where token=@P0 and type=@P1 </inputbuf>
</process>
</process-list>
<resource-list>
<objectlock lockPartition="0" objid="1266103551" subresource="FULL" dbid="6" objectname="xxxx.dbo.cache" id="lock10034ef580" mode="X" associatedObjectId="1266103551">
<owner-list>
<owner id="process117d375c38" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process1180f5d498" mode="S" requestType="wait"/>
</waiter-list>
</objectlock>
<objectlock lockPartition="29" objid="1266103551" subresource="FULL" dbid="6" objectname="xxxx.dbo.cache" id="lock1011729e00" mode="IS" associatedObjectId="1266103551">
<owner-list>
<owner id="process1180f5d498" mode="IS"/>
</owner-list>
<waiter-list>
<waiter id="process117d375c38" mode="X" requestType="wait"/>
</waiter-list>
</objectlock>
</resource-list>
</deadlock>
</deadlock-list>
编辑 #1
-- Results for:
SELECT i.name, i.allow_row_locks, i.allow_page_locks
FROM sys.indexes i
WHERE i.object_id = OBJECT_ID(N'dbo.cache')
name allow_row_locks allow_page_locks
NULL 1 1
IND_cache_token_type 1 1
【问题讨论】:
-
查看快照隔离。这是解决 SELECT 锁定问题的常见对策。
-
@usr:请停止提供不完整的建议。为什么是 SI 而不是 RCSI?
-
@BogdanSahlean 不确定您指的是什么。对于这个问题,我没有时间给出完整的答案。这就是为什么我建议研究这个话题。我不建议只打开它。如果你愿意,我会和你聊聊这个。
-
@usr:请看我的回答,注意#3。
-
@BogdanSahlean 我确实看到了这一点,我投了赞成票。不过,对于只读事务,SI 是 几乎是一个简单的决定。它只是让读者远离锁定和阻塞。我不会因为它可能不合适而忽略它。它可能是合适的,但必须被理解和测试。
标签: sql sql-server sql-server-2012 deadlock