SQL server 死锁图解释
Posted
技术标签:
【中文标题】SQL server 死锁图解释【英文标题】:SQL server deadlock graph explained 【发布时间】:2015-04-02 12:54:45 【问题描述】:我正在测试一个最终同时执行以下存储过程的场景或重复请求
ALTER PROCEDURE [dbo].[clear_class]( @classID [int])
AS
BEGIN
DELETE FROM [dbo].[class_action]
WHERE class_id=@classID;
DELETE FROM [dbo].[page_item_image]
WHERE class_id=@classID;
DELETE pis
FROM [dbo].[page_item_spec] as pis
JOIN page_item AS pit ON (pis.pi_id=pit.pi_id AND pit.pi_owner=@classID)
DELETE FROM [dbo].[page_item]
WHERE pi_owner=@classID;
DELETE FROM [dbo].[page]
WHERE page_owner=@classID;
DELETE FROM [dbo].[image]
WHERE img_owner=@classID;
DELETE FROM [dbo].[class_style]
WHERE class_id=@classID;
DELETE FROM [dbo].[style]
WHERE sty_owner=@classID;
DELETE FROM [dbo].[class_text]
WHERE class_id=@classID;
DELETE FROM [dbo].[text]
WHERE text_owner=@classID;
DELETE FROM [dbo].[action]
WHERE act_owner=@classID;
END
我得到死锁异常。 死锁图如下:
<deadlock-list>
<deadlock victim="process2f7f61848">
<process-list>
<process id="process2f7f61848" taskpriority="0" logused="55572" waitresource="KEY: 5:72057594104315904 (81110f5858a7)" waittime="2947" ownerId="161655" transactionname="user_transaction" lasttranstarted="2015-04-02T15:36:12.427" XDES="0x2effb83b0" lockMode="U" schedulerid="1" kpid="9908" status="suspended" spid="59" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-04-02T15:36:12.427" lastbatchcompleted="2015-04-02T15:36:12.417" lastattention="1900-01-01T00:00:00.417" clientapp="EntityFramework" hostname="MVERG" hostpid="8084" loginname="menelaos" isolationlevel="read committed (2)" xactid="161655" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="db.dbo.p_clear_class" line="15" stmtstart="722" stmtend="874" sqlhandle="0x03000500dfae3842b1f7fa006ea4000001000000000000000000000000000000000000000000000000000000">
DELETE FROM [dbo].[page_item_image] with(rowlock)
WHERE class_id=@classI </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 5 Object Id = 1111011039] </inputbuf>
</process>
<process id="process2f53ff468" taskpriority="0" logused="425956" waitresource="KEY: 5:72057594104119296 (cc50c8bdfc5d)" waittime="2921" ownerId="161454" transactionname="user_transaction" lasttranstarted="2015-04-02T15:36:12.303" XDES="0x2eed31000" lockMode="S" schedulerid="1" kpid="8516" status="suspended" spid="61" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-04-02T15:36:12.303" lastbatchcompleted="2015-04-02T15:36:12.303" lastattention="1900-01-01T00:00:00.303" clientapp="EntityFramework" hostname="MVERG" hostpid="8084" loginname="menelaos" isolationlevel="read committed (2)" xactid="161454" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="db.dbo.p_clear_class" line="40" stmtstart="2108" stmtend="2244" sqlhandle="0x03000500dfae3842b1f7fa006ea4000001000000000000000000000000000000000000000000000000000000">
DELETE FROM [dbo].[text] with(rowlock)
WHERE text_owner=@classI </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 5 Object Id = 1111011039] </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594104315904" dbid="5" objectname="db.dbo.page_item_image" indexname="PK_page_item_image" id="lock2ef2e4900" mode="X" associatedObjectId="72057594104315904">
<owner-list>
<owner id="process2f53ff468" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process2f7f61848" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594104119296" dbid="5" objectname="db.dbo.page_item" indexname="PK_page_item" id="lock2f02ee900" mode="X" associatedObjectId="72057594104119296">
<owner-list>
<owner id="process2f7f61848" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process2f53ff468" mode="S" requestType="wait"/>
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</deadlock-list>
我看到问题与锁定模式有关,表是锁定模式's'并且需要锁定模式'x'但是其他进程已经用'u'锁定了表......
我该怎么做才能解决这个僵局?是因为执行顺序吗? IX 锁是否可以解决任何问题,如果可以,我该如何设置?
【问题讨论】:
任意表之间是否有外键,比如text表和page_item_image表之间? 它们之间没有直接的约束。 'Text' 表很受欢迎,因为它被多个表使用,而不是 page_item_image。 page_item和page_item_image之间有外键吗? 【参考方案1】:我不是 100% 确定,但你可以试试这个,看看它是否有帮助。
目前所有删除语句都在一个批次中执行。因此,如果删除语句获得Exclusive
或Update
锁,则如果它需要访问相同的资源,则以下语句将被阻塞。
创建两个新过程来执行删除语句,分别在它们自己的批处理中。一个用于标准的单表删除语句,一个用于通过连接两个表进行的删除(否则一个 proc 应该就足够了)
删除数据程序
程序一
此过程一次从单个表中删除数据。
CREATE PROCEDURE dbo.usp_Delete_Class
@TableName SYSNAME
,@classID INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @Sql NVARCHAR(MAX);
BEGIN TRANSACTION;
SET @Sql = N'DELETE FROM [dbo].' + QUOTENAME(@TableName)
+ N' WHERE class_id = @classID; '
Exec sp_executesql @Sql
,N'@classID INT'
,@classID
IF @@ERROR = 0
COMMIT TRANSACTION;
ELSE
ROLLBACK TRANSACTION;
END
程序 2
通过连接两个表来删除数据
CREATE PROCEDURE dbo.usp_Delete_Class_page_item_spec
@classID INT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
DELETE pis
FROM [dbo].[page_item_spec] as pis
JOIN page_item AS pit ON (pis.pi_id=pit.pi_id AND pit.pi_owner=@classID)
IF @@ERROR = 0
COMMIT TRANSACTION;
ELSE
ROLLBACK TRANSACTION;
END
主程序
ALTER PROCEDURE [dbo].[clear_class]
@classID INT
AS
BEGIN
SET NOCOUNT ON;
Exec dbo.usp_Delete_Class 'class_action' , @classID
Exec dbo.usp_Delete_Class 'page_item_image' , @classID
Exec dbo.usp_Delete_Class_page_item_spec @classID
Exec dbo.usp_Delete_Class 'page_item' , @classID
Exec dbo.usp_Delete_Class 'page' , @classID
Exec dbo.usp_Delete_Class 'image' , @classID
Exec dbo.usp_Delete_Class 'Class_Style' , @classID
Exec dbo.usp_Delete_Class 'Style' , @classID
Exec dbo.usp_Delete_Class 'Class_Text' , @classID
Exec dbo.usp_Delete_Class 'Text' , @classID
Exec dbo.usp_Delete_Class 'Action' , @classID
END
【讨论】:
不幸的是现在它在Exec dbo.usp_Delete_Class
处死锁:-(以上是关于SQL server 死锁图解释的主要内容,如果未能解决你的问题,请参考以下文章