Sql server 如何避免Insert/Delete语句之间由于非聚集非唯一索引而出现死锁!

Sql server 如何避免Insert/Delete语句之间由于非聚集非唯一索引而出现死锁!,sql-server,database,indexing,deadlock,Sql Server,Database,Indexing,Deadlock,最近,我在客户机的OLTP盒(SQLServer2005)上遇到了一个死锁场景 发现这是由两个不同的线程调用两个存储过程引起的 1,插入在X表中插入数据的sp Insert Into X (col1 , col2 , col3 ) Values ('value 1' , 'value 2' , 'value 3' ) 2、删除从X表中删除数据的sp DELETE X FROM X T1 WITH (NOLOCK) INNER JOIN Y T2 WITH (NO

最近,我在客户机的OLTP盒(SQLServer2005)上遇到了一个死锁场景 发现这是由两个不同的线程调用两个存储过程引起的

1,插入在X表中插入数据的sp

Insert Into X (col1 , col2  , col3  ) 
Values ('value 1' , 'value 2'  , 'value 3'  )
2、删除从X表中删除数据的sp

  DELETE X  
  FROM X T1 WITH (NOLOCK)   
  INNER JOIN Y T2 WITH (NOLOCK)
  ON T1.[col2] = T2.[col2]  
   WHERE t2.date < 'date time value'  
删除X
从X T1到(NOLOCK)
内部连接Y T2与(无锁)
在T1上。[col2]=T2。[col2]
其中t2.date<‘日期时间值’
X表有一个唯一的聚集主键和两个非聚集的非唯一索引。 我通过打开t1222 tace标志分析了死锁,输出总结如下

Insert sp在第1列的非聚集索引上获得了IX锁。 在此期间,Delete sp正在等待列1的同一非聚集索引上的X锁

Delete sp在第2列的非聚集索引上获取了U锁。 在此期间,Insert sp正在等待第2列的同一非聚集索引上的IX锁

任何避免僵局的想法或建议都将不胜感激

编辑

跟踪标志t1222的输出

deadlock-list  
deadlock victim=process3c77d68  
process-list  
process id=process3c12c58 taskpriority=0 logused=1044 waitresource=PAGE: 17:8:7726 waittime=1250 ownerId=5169682909 transactionname=user_transaction lasttranstarted=2011-02-03T03:34:03.443 XDES=0xfe64d78b0 lockMode=IX schedulerid=2 kpid=9544 status=suspended spid=219 sbid=0 ecid=0 priority=0 transcount=2 lastbatchstarted=2011-02-03T03:34:03.457 lastbatchcompleted=2011-02-03T03:34:03.453 clientapp=.Net SqlClient Data Provider hostname=HQMTSRV026 hostpid=3308 loginname=EASUser isolationlevel=read committed (2) xactid=5169682909 currentdb=17 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056  
executionStack  
frame procname=adhoc line=1 stmtend=296 sqlhandle=0x0200000084ce2a1d0e95a5623fa3a9c0981d422e33cab999  
(@1 int<c/>@2 varchar(8000)<c/>@3 nvarchar(4000))INSERT INTO [VB_Audit_TransactionDetail]([ItemID]<c/>[TransactionID]<c/>[ItemValue]) values(@1<c/>@2<c/>@3)
frame procname=adhoc line=1 stmtend=296 sqlhandle=0x02000000afcb1733f435fb93e13556600acf32bb32e10020
Insert Into VB_Audit_TransactionDetail (ItemID  <c/> TransactionID  <c/> ItemValue  ) Values (4 <c/> '0255978c-f56e-477e-b361-8abe62433cff'  <c/> N'HQOLB006'  )  
frame procname=EAS.dbo.SP_Insert line=13 stmtstart=482 stmtend=522 sqlhandle=0x03001100805efa5997d69400719600000100000000000000  
exec (@CommandText)  
inputbuf  
Proc [Database Id = 17 Object Id = 1509580416]  
process id=process3c77d68 taskpriority=0 logused=364 waitresource=PAGE: 17:6:334008 waittime=1234 ownerId=5169682116 transactionname=user_transaction lasttranstarted=2011-02-03T03:34:03.053 XDES=0xa8e297cd0 lockMode=X schedulerid=12 kpid=10300 status=suspended spid=327 sbid=0 ecid=0 priority=0 transcount=2 lastbatchstarted=2011-02-03T03:33:41.137 lastbatchcompleted=2011-02-03T03:33:41.133 clientapp=Microsoft SQL Server hostname=HQSSISSRV002 hostpid=7632 loginname=NBKDOM\SQLCSRVC isolationlevel=read committed (2) xactid=5169682116 currentdb=17 lockTimeout=4294967295 clientoption1=671350816 clientoption2=128056  
executionStack  
frame procname=EAS.dbo.PurgeAuditTransactionTables line=59 stmtstart=4202 stmtend=4728 sqlhandle=0x030011006354a2313d11ae00979a00000100000000000000  
DELETE [dbo].[Audit_TransactionDetail]  
FROM [dbo].[Audit_TransactionDetail] T1 WITH (NOLOCK)  
INNER JOIN [dbo].[Audit_NBKTransaction] T2 WITH (NOLOCK)ON T1.[TransactionID] = T2.[TransactionID]  
WHERE TransactionPostedDateTime < @LastReplicationDateTime  
frame procname=adhoc line=1 sqlhandle=0x0100110096968c0560c430ff190000000000000000000000  
EXEC PurgeAuditTransactionTables '02 Feb 2011 19:00:13:870'  
inputbuf  
EXEC PurgeAuditTransactionTables '02 Feb 2011 19:00:13:870'  
resource-list  
pagelock fileid=8 pageid=7726 dbid=17 objectname=EAS.dbo.Audit_TransactionDetail id=lock4f79500 mode=U associatedObjectId=886415243542528  
owner-list  
owner id=process3c77d68 mode=U  
waiter-list  
waiter id=process3c12c58 mode=IX requestType=wait  
pagelock fileid=6 pageid=334008 dbid=17 objectname=EAS.dbo.Audit_TransactionDetail id=lock846afca00 mode=IX associatedObjectId=604940266831872  
owner-list  
owner id=process3c12c58 mode=IX  
waiter-list  
waiter id=process3c77d68 mode=X requestType=wait  
死锁列表 死锁受害者=进程3C77D68 进程列表 进程id=process3c12c58 taskpriority=0 logused=1044 waitresource=PAGE:17:8:7726 waittime=1250 ownerId=5169682909 transactionname=user_transaction lasttranstarted=2011-02-03T03:34:03.443 XDES=0xfe64d78b0锁定模式=IX schedulerid=2 kpid=9544状态=挂起spid=219 sbid=0 ecid=0优先级=0 transcount=2 lastbatchstarted=2011-02-03T03:34:03.457lastbatchcompleted=2011-02-03T03:34:03.453 clientapp=.Net SqlClient数据提供程序hostname=HQMTSRV026 hostpid=3308 loginname=EASUser isolationlevel=read committed(2)xactid=5169682909 currentdb=17 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056 执行堆栈 帧procname=adhoc line=1 stmtend=296 sqlhandle=0x02000000084CE2A1D0E95A5623FA3A9C0981D422E33CAB999 (@1 int@2varchar(8000)@3 nvarchar(4000))插入[VB_Audit_TransactionDetail]([ItemID][TransactionID][ItemValue])值(@1@2@3) 帧procname=adhoc line=1 stmtend=296 sqlhandle=0x020000000AFCB1733F435FB93E13556600ACF32BB32E1002 将值(4'0255978c-f56e-477e-b361-8abe62433cff'N'HQOLB006'插入VB_审计_事务细节(ItemID TransactionID ItemValue) frame procname=EAS.dbo.SP_Insert line=13 stmtstart=482 stmtend=522 sqlhandle=0x03001100805EFA5997D69400719600000000000000 exec(@CommandText) 输入 Proc[数据库Id=17对象Id=1509580416] 进程id=process3c77d68 taskpriority=0 logused=364 waitresource=PAGE:17:6:334008 waittime=1234 ownerId=5169682116 transactionname=user_transaction lasttranstarted=2011-02-03T03:34:03.053 XDES=0xa8e297cd0 lockMode=X schedulerid=12 kpid=10300 status=suspended spid=327 sbid=0 ecid=0 priority=0 transcount=2 lastbatchstarted=2011-02-03T03:33:41.137lastbatchcompleted=2011-02-03T03:33:41.133 clientapp=Microsoft SQL Server主机名=HQSSISRV002主机PID=7632 loginname=NBKDOM\SQLCSRVC isolationlevel=read committed(2)xactid=5169682116 currentdb=17锁超时=4294967295 clientoption1=671350816 clientoption2=128056 执行堆栈 frame procname=EAS.dbo.PurgeAuditTransactionTables行=59 stmtstart=4202 stmtend=4728 sqlhandle=0x030011006354A2313D11AE00979A000000000000000 删除[dbo]。[Audit\u TransactionDetail] 来自[dbo]。[Audit_TransactionDetail]T1,带(NOLOCK) 内部联接[dbo].[Audit\u NBKTransaction]T2与T1上的(NOLOCK)[TransactionID]=T2.[TransactionID] 其中TransactionPostedDateTime<@LastReplicationDateTime 帧procname=adhoc line=1 sqlhandle=0x0100110096968C0560C430FF190000000000000000 EXEC PurgeAuditTransactionTables'2011年2月2日19:00:13:870' 输入 EXEC PurgeAuditTransactionTables'2011年2月2日19:00:13:870' 资源列表 pagelock fileid=8 pageid=7726 dbid=17 objectname=EAS.dbo.Audit\U TransactionDetail id=lock4f79500 mode=U associatedObjectId=88641524354228 业主名单 所有者id=process3c77d68模式=U 服务员名单 服务员id=process3c12c58模式=IX请求类型=wait pagelock fileid=6 pageid=334008 dbid=17 objectname=EAS.dbo.Audit\U TransactionDetail id=lock846afca00 mode=IX associatedObjectId=604940266831872 业主名单 所有者id=process3c12c58模式=IX 服务员名单 服务员id=process3c77d68模式=X请求类型=wait

还有一件事很重要;delete和insert语句始终涉及两组不同的数据

我猜T2表一定很大。t2.date列是否已编制索引?如果没有,那么在一个大的表上进行表扫描可能会导致您的问题。索引该列可以通过避免表扫描来优化删除。或者,如果col1或col2上的索引没有被真正使用(或使用得不够),删除它们也可以避免问题

这些死锁多久发生一次?如果它们很少出现,一个笨拙的变通方法可能就足够了:将每个语句包装在try/catch块中,在catch检查中检查错误是否是由死锁引起的,如果是,则重试该命令。您还可以小心地使用
SET DEADLOCK\u PRIORITY
来选择哪个查询总是赢/输(但您必须在所有对表的调用之间取得平衡)


哦,用(NOLOCK)s扔掉那些
。NOLOCK会被插入、更新和删除忽略。

与其描述您对死锁图的理解,不如发布死锁图本身。XML,而不是图形呈现的位图。乍一看,所涉及的IX锁上存在冲突这一事实表明正在发生锁升级,这表明没有索引为删除服务,或者连接上的索引转折点已命中。但是,由于信息不足,这只是猜测。要给出任何有意义的答案,需要实际的死锁XML和所涉及对象的确切模式定义

更新后