经过 5 年的工作,SQL Server 2k5 表现在锁定,无需对数据库进行任何更改

Pet*_*ock 5 sql-server-2005 deadlock

我有一张桌子:OrderDetails

5 年来,只发生了奇怪的死锁。如果它发生了,它发生在OrderDetails表上的索引上现在突然间,死锁无处不在 - 发生的时间很短。我们没有对应用程序或数据库进行任何更改 - 每周都会重建索引。

问题是OrderDetails现在桌子有时会被锁住,所有的地狱都崩溃了

有人可以帮忙看看他们是否从日志中发现任何东西:我怎样才能摆脱整个OrderDetails表上的 objectLock ?为什么表会锁定 - 过去只有索引会导致死锁。这是否意味着索引未能找到合适的记录,现在整个表都被锁定了?

这是一个Update和一个Select在这里死锁,并且被锁定的行不相关 - 它们没有相同的参考号或OrderID

 spid18s,Unknown,waiter id=process91bb58 mode=X requestType=convert
 spid18s,Unknown,waiter id=process9a9018 mode=S requestType=convert
 spid18s,Unknown,waiter-list
 spid18s,Unknown,owner id=process9a9018 mode=IS
 spid18s,Unknown,owner id=process91bb58 mode=IX
 spid18s,Unknown,owner-list
 spid18s,Unknown,objectlock lockPartition=0 objid=1194487334 subresource=FULL dbid=5 objectname=CompZ.dbo.OrderDetails id=lock32163640 mode=IX associatedObjectId=1194487334
 spid18s,Unknown,resource-list
 spid18s,Unknown,Proc [Database Id = 5 Object Id = 711009614]
 spid18s,Unknown,inputbuf
 spid18s,Unknown,OrderNoRef = @OrderNoRef and ClientID = @ClientID and  OrderNo <> @OrderNo
 spid18s,Unknown,where
 spid18s,Unknown,select  Distinct OrderNoRef from OrderDetails
 spid18s,Unknown,frame procname=CompZ.dbo.SP_Duplicate_Ref line=12 stmtstart=530 sqlhandle=0x030005004e25612a5f3d2a0194a100000100000000000000
 spid18s,Unknown,executionStack
 spid18s,Unknown,process id=process9a9018 taskpriority=0 logused=0 waitresource=OBJECT: 5:1194487334:0  waittime=8640 ownerId=17099323 transactionname=SELECT lasttranstarted=2013-06-11T14:34:34.230 XDES=0x2567fb58 lockMode=S schedulerid=2 kpid=15548 status=suspended spid=76 sbid=0 ecid=0 priority=0 transcount=0 lastbatchstarted=2013-06-11T14:34:26.570 lastbatchcompleted=2013-06-11T14:34:26.570 clientapp=.Net SqlClient Data Provider hostname=WEBSVR hostpid=16664 loginname=*** isolationlevel=read committed (2) xactid=17099323 currentdb=5 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
 spid18s,Unknown,Proc [Database Id = 5 Object Id = 562101043]
 spid18s,Unknown,inputbuf
 spid18s,Unknown,Update OrderDetails set OrderState = 15 where OrderNo = @OrderNo And OrderState in (1,2,3)
 spid18s,Unknown,frame procname=CompZ.dbo.SP_Insert_OrderDet line=59 stmtstart=1726 stmtend=1890 sqlhandle=0x0300050033fb8021a4e1360011a100000100000000000000
 spid18s,Unknown,executionStack
 spid18s,Unknown,process id=process91bb58 taskpriority=0 logused=0 waitresource=OBJECT: 5:1194487334:0  waittime=8609 ownerId=17099322 transactionname=UPDATE lasttranstarted=2013-06-11T14:34:34.230 XDES=0x3a2844e0 lockMode=X schedulerid=1 kpid=23896 status=suspended spid=63 sbid=0 ecid=0 priority=0 transcount=2 lastbatchstarted=2013-06-11T14:34:25.347 lastbatchcompleted=2013-06-11T14:34:25.327 clientapp=.Net SqlClient Data Provider hostname=WEBSVR hostpid=16664 loginname=*** isolationlevel=read committed (2) xactid=17099322 currentdb=5 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
 spid18s,Unknown,process-list
 spid18s,Unknown,deadlock victim=process9a9018
 spid18s,Unknown,deadlock-list
Run Code Online (Sandbox Code Playgroud)

其中一个索引删除了页面和行锁(没有记录在案,所以我不知道这一点 - 我很抱歉声明标题中没有任何变化) - 如果行和页面都锁定了一个索引被禁用,它会锁定使用该索引的表吗?(是的,如果行锁和页锁被关闭,那么只有表锁可用。)

Dav*_*tch 1

使用 SQL Profiler 跟踪死锁并找到一些作为根本原因的示例查询。

然后将该 SQL 复制到 SSMS 并查看其执行计划。

查看查询运行时持有哪种类型的锁。

几乎可以肯定您遇到了表锁 - 实际上,正如您所说,有人删除了行级锁和页级锁。

您有以下选择:

  1. 修改您的 SELECT 语句以使用 READ UNCOMMITTED 或 (nolock)。这意味着该查询可以读取脏数据。只有您知道这对于您的数据集是否可以接受 - 通常,脏读是可以接受的,并且不会影响系统的功能。

  2. 使用行级锁。您可以使用查询提示强制执行这些操作。

  3. 使用行版本控制 - 此选项意味着更新对与 SELECT 语句正在读取的行不同版本的行进行操作,从而完全避免死锁。

您可以在此处找到有关行版本控制和其他死锁减少技术的更多详细信息。