我一直在
Caused by: java.sql.SQLException: Transaction (Process ID 61) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
所以我使用
打开了mssql日志DBCC TRACEON(1222,-1)
DBCC TRACEON(1204,-1)
并在日志中打印死锁信息:
这些行表示已检测到死锁,并且已选择进程1作为受害者。
process-list
deadlock victim=PROCESS_ID_1
deadlock-list
process_id_1的日志
[1] (@P0 nvarchar(4000))select namesequen0_.id as id1_47_<c/> namesequen0_.container_id as containe9_47_<c/> namesequen0_.increment_ as incremen2_47_<c/> namesequen0_.nextValue as nextValu3_47_<c/> namesequen0_.numChars as numChars4_47_<c/> namesequen0_.padChar as padChar5_47_<c/> namesequen0_.scope as scope6_47_<c/> namesequen0_.sequenceType as sequence7_47_<c/> namesequen0_.uppercase as uppercas8_47_ from NameSequence namesequen0_ where (namesequen0_.scope like @P0 ) and (namesequen0_.container_id is null)
[2] frame procname=adhoc line=1 stmtstart=40 sqlhandle=0x020000005734e00acfb3060d49cc0e8565acb3b105807744
[3] executionStack
[4] process id=PROCESS_ID_1 taskpriority=0 logused=1248 waitresource=KEY: 14:72057594053459968 (95c9fddfaf17) waittime=3506 ownerId=13645568 transactionname=implicit_transaction lasttranstarted=2015-06-02T07:52:41.660 XDES=0xa30dd950 lockMode=S schedulerid=1 kpid=1848 status=suspended spid=68 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2015-06-02T07:52:41.663 lastbatchcompleted=2015-06-02T07:52:41.660 clientapp=jTDS hostname=QALAB6 hostpid=123 loginname=qalab6_nrm isolationlevel=read committed (2) xactid=13645568 currentdb=14 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128058
process_id_2的日志
[1]select card0_.id as id2_77_<c/> card0_.autoDisplayName as autoDisp3_77_<c/> card0_.autoPartialName as autoPart4_77_<c/> card0_.namedWithSequence_id as namedWi38_77_<c/> card0_.namedWithSequenceValue as namedWit5_77_<c/> card0_.userDisplayName as userDisp6_77_<c/> card0_.userPartialName as userPart7_77_<c/> card0_.lifeCycleState_id as lifeCyc40_77_<c/> card0_.model_id as model41_77_<c/> card0_.outOfService as outOfSe12_77_<c/> card0_.bottomClearance as bottomC13_77_<c/> card0_.leftClearance as leftCle14_77_<c/> card0_.rightClearance as rightCl15_77_<c/> card0_.topClearance as topClea16_77_<c/> card0_.ncmElementKey as ncmElem24_77_ from VfdItem card0_ where card0_.DTYPE='Card' and card0_.ncmElementKey= @P0
[2]frame procname=adhoc line=1 stmtstart=40 sqlhandle=0x02000000386ba721896ce39b0b7c9d01df11539c0d843c83
[3]executionStack
[4]process id=PROCESS_ID_2 taskpriority=0 logused=62048 waitresource=KEY: 14:72057594051297280 (fadae9b0c9d3) waittime=3333 ownerId=13645330 transactionname=implicit_transaction lasttranstarted=2015-06-02T07:52:39.570 XDES=0xbf9f5950 lockMode=S schedulerid=1 kpid=5344 status=suspended spid=66 sbid=0 ecid=0 priority=0 trancount=1 lastbatchstarted=2015-06-02T07:52:41.833 lastbatchcompleted=2015-06-02T07:52:41.813 clientapp=jTDS hostname=QALAB6 hostpid=123 loginname=qalab6_nrm isolationlevel=read committed (2) xactid=13645330 currentdb=14 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128058
现在,以下行提供了process_id_1的详细信息,
Ref [1]是我们要执行的查询...注意:它对表名NameSequence
和namesequence0_.container_id
的选择查询是表名{{1}的外键}}
Ref [4]表示它正在等待资源并被暂停
现在,以下行提供了与vfditem
process_id_2
的详细信息
参考[1]让查询process_id_1
想要运行...注意它对表名process_id_2
的选择查询,vfditem
是表名{{}的外键1}}
Ref [4]表示它正在等待资源并被暂停
现在,以下行会打印所有被锁定的资源以及由谁和谁在等待该资源。
card0_.namedWithSequence_id
这转化为
[1]资源NameSequence
在独占锁定模式下被[11] waiter id=PROCESS_ID_2 mode=S requestType=wait
[10] waiter-list
[9] owner id=PROCESS_ID_1 mode=X
[8] owner-list
[7] keylock hobtid=72057594051297280 dbid=14 objectname=qalab6_nrm.dbo.vfditem indexname=vfditem_pk id=lock85330d00 mode=X associatedObjectId=72057594051297280
[6] waiter id=PROCESS_ID_1 mode=S requestType=wait
[5] waiter-list
[4] owner id=PROCESS_ID_2 mode=X
[3] owner-list
[2] keylock hobtid=72057594053459968 dbid=14 objectname=qalab6_nrm.dbo.namesequence indexname=NameSequence_PK id=lock848c3380 mode=X associatedObjectId=72057594053459968
[1] resource-list
锁定,而qalab6_nrm.dbo.namesequence indexname=NameSequence_PK
正在等待它。
[2]资源process_id_2
在独占锁定模式下被process_id_1
锁定,而qalab6_nrm.dbo.vfditem indexname=vfditem_pk
正在等待它。
BINGO 我们可以看到它是如何陷入僵局的
现在奇怪的部分
如果仔细观察,process_id_1
尝试从表名process_id_2
运行选择查询,列process_id_1
是表NameSequence
和{{1}的外键}已经获得了对NameSequence.container_id
[1]为什么vfditem
会获得对vfditem索引的锁定?
进一步process_id_1
正在尝试从表名indexname=vfditem_pk of vfditem table
运行选择查询,列process_is_1
是来自表process_id_2
的外键,而vfditem
已经获得了对vfditem.namesequence_id
[2]为什么NameSequence
会获取对Namesequence索引的锁定?
答案 0 :(得分:0)
MSSQL在select语句上使用锁定,它可以执行表,页和行锁。这实际上取决于你想在你的系统中做什么以及什么更重要但是一路上的一个好指针是查看你可以放在SELECT语句上的Table Hints,特别是{{1} },NOWAIT
,NOLOCK
和READCOMMITTED
您可能还需要考虑在所有交易中设置Isolation Level,以避免在其他地方出现此问题。
这是一些非常基本的信息,DBA可能能够提供更详细的答案,但这些选项可以防止这个问题发生
您可以通过运行READ_COMMITTED_SNAPSHOT
告诉您的隔离级别,并且可以通过运行DBCC useroptions
来告诉read_committed_snapshot