我在SQL Server -2014标准版上面临死锁问题。两个插入在聚集索引上陷入死锁。
它是一个OLTP数据库,表是高插入和高读取,表已经具有聚簇索引的主键并且有超过1300万条记录
SQL语句如下所示
<deadlock>
<victim-list>
<victimProcess id="processa19016ca8" />
</victim-list>
<process-list>
<process id="processa19016ca8" taskpriority="0" logused="3888" waitresource="KEY: 9:72057699966713856 (ffffffffffff)" waittime="1034" ownerId="1298235110" transactionname="user_transaction" lasttranstarted="2017-06-20T11:52:42.003" XDES="0x714fe0d90" lockMode="RangeI-N" schedulerid="1" kpid="7856" status="suspended" spid="66" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-06-20T11:52:42.830" lastbatchcompleted="2017-06-20T11:52:42.820" lastattention="1900-01-01T00:00:00.820" clientapp=".Net SqlClient Data Provider" hostname="WIN-2HO2RRV99BU" hostpid="2980" loginname="sa" isolationlevel="serializable (4)" xactid="1298235110" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="1236" stmtend="3454" sqlhandle="0x0200000064f4502b431082b3ac55b13757583f58c2c98c7c0000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@p0 bigint,@p1 datetime,@p2 nvarchar(4000),@p3 int,@p4 float,@p5 int,@p6 datetime,@p7 int,@p8 datetime,@p9 nvarchar(4000),@p10 int,@p11 bigint,@p12 float,@p13 float,@p14 nvarchar(4000),@p15 nvarchar(4000),@p16 float,@p17 int,@p18 nvarchar(4000),@p19 int,@p20 float,@p21 float,@p22 int,@p23 int,@p24 float,@p25 nvarchar(4000),@p26 float,@p27 float,@p28 float,@p29 int,@p30 bigint,@p31 bigint,@p32 nvarchar(4000),@p33 float,@p34 float,@p35 nvarchar(4000),@p36 int,@p37 int,@p38 float,@p39 int,@p40 bigint,@p41 float,@p42 float,@p43 nvarchar(4000),@p44 datetime,@p45 int,@p46 nvarchar(4000),@p47 int,@p48 nvarchar(4000))INSERT INTO [dbo].[PatientBilledItem]([PatientBillUID], [EventOccuredDttm], [ServiceName], [BillableItemUID], [Amount], [CUser], [CWhen], [MUser], [MWhen], [StatusFlag], [OwnerOrganisationUID], [PatientBillableItemUID], [Discount], [NetAmount], [Description], [Comments], [ItemMultiplier], [BSMDDUID], [ItemName], [DiscountAuthorizedBy], [ConsultantShare], [ServiceTax], [CareProviderUID], [QNUOMUID], [Sp </inputbuf>
</process>
<process id="process18572db848" taskpriority="0" logused="3896" waitresource="KEY: 9:72057699966713856 (ffffffffffff)" waittime="1012" ownerId="1298235129" transactionname="user_transaction" lasttranstarted="2017-06-20T11:52:42.027" XDES="0x1ada4fed90" lockMode="RangeI-N" schedulerid="1" kpid="14928" status="suspended" spid="118" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-06-20T11:52:42.853" lastbatchcompleted="2017-06-20T11:52:42.847" lastattention="1900-01-01T00:00:00.847" clientapp=".Net SqlClient Data Provider" hostname="WIN-PGECRKPS51J" hostpid="3092" loginname="sa" isolationlevel="serializable (4)" xactid="1298235129" currentdb="9" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="1236" stmtend="3454" sqlhandle="0x0200000064f4502b431082b3ac55b13757583f58c2c98c7c0000000000000000000000000000000000000000">
unknown </frame>
<frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@p0 bigint,@p1 datetime,@p2 nvarchar(4000),@p3 int,@p4 float,@p5 int,@p6 datetime,@p7 int,@p8 datetime,@p9 nvarchar(4000),@p10 int,@p11 bigint,@p12 float,@p13 float,@p14 nvarchar(4000),@p15 nvarchar(4000),@p16 float,@p17 int,@p18 nvarchar(4000),@p19 int,@p20 float,@p21 float,@p22 int,@p23 int,@p24 float,@p25 nvarchar(4000),@p26 float,@p27 float,@p28 float,@p29 int,@p30 bigint,@p31 bigint,@p32 nvarchar(4000),@p33 float,@p34 float,@p35 nvarchar(4000),@p36 int,@p37 int,@p38 float,@p39 int,@p40 bigint,@p41 float,@p42 float,@p43 nvarchar(4000),@p44 datetime,@p45 int,@p46 nvarchar(4000),@p47 int,@p48 nvarchar(4000))INSERT INTO [dbo].[PatientBilledItem]([PatientBillUID], [EventOccuredDttm], [ServiceName], [BillableItemUID], [Amount], [CUser], [CWhen], [MUser], [MWhen], [StatusFlag], [OwnerOrganisationUID], [PatientBillableItemUID], [Discount], [NetAmount], [Description], [Comments], [ItemMultiplier], [BSMDDUID], [ItemName], [DiscountAuthorizedBy], [ConsultantShare], [ServiceTax], [CareProviderUID], [QNUOMUID], [Sp </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057699966713856" dbid="9" objectname="HEALTHOBJECT.dbo.PatientBilledItem" indexname="IX_PatientBillableItem" id="lock28bc25a00" mode="RangeS-S" associatedObjectId="72057699966713856">
<owner-list>
<owner id="process18572db848" mode="RangeS-S" />
<owner id="process18572db848" mode="RangeI-N" requestType="convert" />
</owner-list>
<waiter-list>
<waiter id="processa19016ca8" mode="RangeI-N" requestType="convert" />
</waiter-list>
</keylock>
<keylock hobtid="72057699966713856" dbid="9" objectname="HEALTHOBJECT.dbo.PatientBilledItem" indexname="IX_PatientBillableItem" id="lock28bc25a00" mode="RangeS-S" associatedObjectId="72057699966713856">
<owner-list>
<owner id="processa19016ca8" mode="RangeS-S" />
<owner id="processa19016ca8" mode="RangeI-N" requestType="convert" />
</owner-list>
<waiter-list>
<waiter id="process18572db848" mode="RangeI-N" requestType="convert" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
是的,表也有触发器
附加事件XML
num1=50
def func():
print(num1)
num1=100
func()
答案 0 :(得分:0)
单独INSERT不会相互死锁。如果您在同一事务中调用SELECT WHERE UID=SCOPE_IDENTITY()
,则服务器必须对包含UID的任何索引进行SHARED锁定。那是因为你试图读取SCOPE_IDENTITY()
的值,如果添加了另一行,它将改变,导致数据不一致。如果使用REPEATABLE READ隔离级别,最终可能会出现死锁。
解决方案非常简单 - 不要使用单独的SELECT。您可以使用INSERT的OUTPUT clause来获取所有新值,例如标识,默认值等:
INSERT INTO [dbo].[PatientBilledItem]
([PatientBillUID], [EventOccuredDttm], [ServiceName], [BillableItemUID], [Amount], [CUser], [CWhen], [MUser], [MWhen], [StatusFlag], [OwnerOrganisationUID], [PatientBillableItemUID], [Discount], [NetAmount], [Description], [Comments], [ItemMultiplier], [BSMDDUID], [ItemName], [DiscountAuthorizedBy], [ConsultantShare], [ServiceTax], [CareProviderUID], [QNUOMUID], [SpecialAmount], [IsRefunded], [ConsultantDiscount], [EducationCess], [HigherEducationCess], [RecordedByUID], [OriginalCreditBillUID], [PatientPackageItemUID], [BatchID], [VATPercentage], [InternalCost], [CalculateTaxOnMRP], [StoreUID], [BillPackageUID], [SplitDiscount], [RSLVLUID], [ParentUID], [PackageItemAmount], [RoundOff], [AuthNo], [ExpiryDttm], [BILGRDUID], [ApprovalCode], [ApprovedBy], [InternalBatchID])
OUTPUT inserted.UID,inserted.Timestamp
VALUES ......
您可以将其与SNAPSHOT隔离级别结合使用,以减少事务之间的阻塞。
答案 1 :(得分:0)
根据提供的信息,首先假设这些死锁是由以下缺失索引之一引起的
CREATE /*UNIQUE*/ NONCLUSTERED INDEX IUN_PatientBilledItem_UID_#_TIMESTAMP
ON dbo.PatientBilledItem (UID)
INCLUDE(TIMESTAMP)
或
CREATE /*UNIQUE*/ NONCLUSTERED INDEX IUN_PatientBilledItem_UID_TIMESTAMP
ON dbo.PatientBilledItem (UID, TIMESTAMP)
遵循SELECT
语句需要:
SELECT [t0].[UID], [t0].[TIMESTAMP]
FROM [dbo].[PatientBilledItem] AS [t0]
WHERE [t0].[UID] = (SCOPE_IDENTITY())
生成RangeS-S
锁定(也因为TX隔离级别为SERIALIZABLE
)。
注意:如果当前索引具有唯一值或唯一值对(复合索引),则取消注释/*UNIQUE*/
关键字。