这篇文章将为大家详细讲解有关公司仓库数据库服务器死锁过程及解决办法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

死锁的四个必要条件:

互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。

请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。

非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。

循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

仓库拣货卡死,排查了数据库的很多地方,都没有头绪,最后到SQL Server 错误日志里查看,终于发现了蛛丝马迹

EXECxp_readerrorlog0,1,NULL,NULL,'2015-09-21','2015-10-10','DESC'waiterid=process5c30e08mode=UrequestType=waitwaiter-listownerid=process5c26988mode=Xowner-listkeylockhobtid=72057597785604096dbid=33objectname=stoxxx.dbo.Orderxxxindexname=IX_PricingExpressProductCode_Stateid=lock17fa96980mode=XassociatedObjectId=72057597785604096waiterid=process5c26988mode=UrequestType=waitwaiter-listownerid=process5c30e08mode=Xowner-listkeylockhobtid=72057597785604096dbid=33objectname=stoxxx.dbo.Orderxxxindexname=IX_PricingExpressProductCode_Stateid=lock87d69e780mode=XassociatedObjectId=72057597785604096resource-list(@OperateStatemoney,@HandledByNewWmsbit,@Stateint,@OrderOutint)UPDATE[Orderxx]SET[OperateState]=@OperateState,[HandledByNewWms]=@HandledByNewWmsWHERE(([Orderxxx].[State]=@State)And([Orderxxx].[OrderOut]=@OrderOut)And([Orderxxx].[PricingExpressProductCode]IN('UKNIR')))inputbufunknownframeprocname=unknownline=1sqlhandle=0x000000000000000000000000000000000000000000000000UPDATE[Orderxxx]SET[OperateState]=@OperateState,[HandledByNewWms]=@HandledByNewWmsWHERE(([Orderxxx].[State]=@State)And([Orderxxx].[OrderOut]=@OrderOut)And([Orderxxx].[PricingExpressProductCode]IN('UKNIR')))frameprocname=adhocline=1stmtstart=134sqlhandle=0x020000009d376d18a17e7ea51289d8caa2fb4de65c976389executionStackprocessid=process5c30e08taskpriority=0logused=10320waitresource=KEY:33:72057597785604096(112399c2054a)waittime=4813ownerId=31578743038transactionname=user_transactionlasttranstarted=2015-09-24T10:22:58.410XDES=0x372e95950lockMode=Uschedulerid=17kpid=8496status=suspendedspid=153sbid=0ecid=0priority=0trancount=2lastbatchstarted=2015-09-24T10:22:58.540lastbatchcompleted=2015-09-24T10:22:58.540clientapp=.NetSqlClientDataProviderhostname=CK1-WIN-WEB02hostpid=37992loginname=ck1.bizisolationlevel=readcommitted(2)xactid=31578743038currentdb=33lockTimeout=4294967295clientoption1=671088672clientoption2=128056(@OperateStatemoney,@HandledByNewWmsbit,@Stateint,@OrderOutint)UPDATE[Orderxxx]SET[OperateState]=@OperateState,[HandledByNewWms]=@HandledByNewWmsWHERE(([Orderxxx].[State]=@State)And([Orderxxx].[OrderOut]=@OrderOut)And([Orderxxx].[PricingExpressProductCode]IN('UKNIR')))inputbufunknownframeprocname=unknownline=1sqlhandle=0x000000000000000000000000000000000000000000000000UPDATE[Orderxxx]SET[OperateState]=@OperateState,[HandledByNewWms]=@HandledByNewWmsWHERE(([Orderxxx].[State]=@State)And([Orderxxx].[OrderOut]=@OrderOut)And([Orderxxx].[PricingExpressProductCode]IN('UKNIR')))frameprocname=adhocline=1stmtstart=134sqlhandle=0x020000009d376d18a17e7ea51289d8caa2fb4de65c976389executionStackprocessid=process5c26988taskpriority=0logused=9892waitresource=KEY:33:72057597785604096(70f5b089bb2b)waittime=4813ownerId=31579268946transactionname=user_transactionlasttranstarted=2015-09-24T10:27:01.357XDES=0x98312f950lockMode=Uschedulerid=16kpid=9184status=suspendedspid=454sbid=0ecid=0priority=0trancount=2lastbatchstarted=2015-09-24T10:27:01.490lastbatchcompleted=2015-09-24T10:27:01.487clientapp=.NetSqlClientDataProviderhostname=CK1-WIN-WEB02hostpid=37992loginname=ck1.bizisolationlevel=readcommitted(2)xactid=31579268946currentdb=33lockTimeout=4294967295clientoption1=671088672clientoption2=128056process-listdeadlockvictim=process5c26988deadlock-list

咋一看上面的错误信息,可以发现两条相同的语句造成的死锁,但是这么短的语句不可能持有排他锁太久

再仔细分析一下错误日志,发现都死锁在同一个非聚集索引上,再问了一下开发,开发那边说,这条语句是在一个大事务里面,这个事务会做7、8件事

索引属性

还有索引里面的数据,发现很多重复值

SQL语句是这样的

(@OperateStatemoney,@HandledByNewWmsbit,@Stateint,@OrderOutint)@HandledByNewWms=(1)@OperateState=($1.0000)@OrderOut=(4055484)@State=(3)UPDATE[Orderxxx]SET[OperateState]=$1.0000,[HandledByNewWms]=1WHERE(([Orderxxx].[State]=3)And([Orderxxx].[OrderOut]=4055484)And([Orderxxx].[PricingExpressProductCode]IN('UKRRM','UKRLE')))

下图为语句生成的执行计划

当时的情况是大量SQL语句被阻塞,而阻塞的语句正是下面这条语句

UPDATE[Orderxxx]SET[OperateState]=$1.0000,[HandledByNewWms]=1WHERE(([Orderxxx].[State]=3)And([Orderxxx].[OrderOut]=4055484)And([Orderxxx].[PricingExpressProductCode]IN('UKRRM','UKRLE')))

解决方法

上面得出几个症状

1、update语句是在一个大事务里面,事务太大导致其他session等待排他锁的时间变长

2、大家都在使用同一个非聚集索引,并扫描PricingExpressProductCode字段

3、索引里的重复值很多

从上面的症状基本可以判断,这个非聚集索引无啥用,可以禁用之

ALTERINDEX[IX_PricingExpressProductCode_State]ON[dbo].[Orderxxx]DISABLE

禁用之后,死锁消失,问题解决,仓库的怨气也随之消失

这一次排查过程时间有点长,但是很好定位,SQL Server错误日志给出了足够的信息定位死锁问题,所以遇到问题的时候一定要分析清楚日志

关于公司仓库数据库服务器死锁过程及解决办法是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。