异步 SELECT 语句导致 SQL Server 临时表死锁

问题描述 投票:0回答:1

我们有一个用 C# 建立异步数据库连接的应用程序,它尝试同时运行两个

SELECT
语句。两个语句都引用相同的临时表,但只是
SELECT
,但我们看到发生死锁和操作错误。

死锁图表明双方具有相同的 SPID,并显示它正在尝试获取 tempdb 对象(临时表)上的独占锁。在旧版本的 SQL Server 中,相同数据上的相同代码可以工作,但在测试迁移到 SQL Server 2019 时,我们发现死锁导致应用程序中出现错误。通过全局启用跟踪标志 1204 和 1222 确定导致死锁的对象是临时表。

来自SQL错误日志:

objectlock lockPartition=0 objid=-1598015006 subresource=FULL dbid=2 objectname=tempdb.dbo.#TempTable__________________________________________________________________________________________________________0000000049FC id=lock219d47a4c80 mode=X associatedObjectId=-1598015006

当我们更改 C# 以串行方式进行调用(无异步)时,不会出现错误 - 这是有道理的,因为没有对同一 tempdb 对象的并发访问。

在旧的 SQL 版本中,我们没有死锁。两个实例之间唯一明显的区别是 SQL Server 版本。将 mdf/ldf 从 SQL Server 2016 实例复制到 SQL Server 2019 实例并附加。两者的兼容性级别相同。

编辑:死锁 XML 报告

<deadlock>
 <victim-list>
  <victimProcess id="process21a00a2b848" />
 </victim-list>
 <process-list>
  <process id="process21a00a2b848" taskpriority="0" logused="0" waitresource="OBJECT: 2:-1346206128:0 " waittime="2837" ownerId="25719004" transactionname="SELECT" lasttranstarted="2024-01-12T10:19:32.853" XDES="0x21568dce188" lockMode="X" schedulerid="13" kpid="10232" status="suspended" spid="147" sbid="2" ecid="0" priority="0" trancount="0" lastbatchstarted="2024-01-12T10:19:32.817" lastbatchcompleted="2024-01-12T10:19:31.813" lastattention="1900-01-01T00:00:00.813" clientapp=".Net SqlClient Data Provider" hostname="HOSTMACH1" hostpid="11172" loginname="DOMAIN1\Account1" isolationlevel="read committed (2)" xactid="25719004" currentdb="6" currentdbname="TestDB1" lockTimeout="4294967295" clientoption1="671088928" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="2" stmtstart="838" stmtend="6934" sqlhandle="0x020000008e6ea223919a9751bfa1ae026e9f70a4edb236af0000000000000000000000000000000000000000">
unknown    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@Var0 nvarchar(36),@Var1 nvarchar(36),@Var2 nvarchar(36),@Var3 nvarchar(36),@Var4 nvarchar(36),@Var5 nvarchar(36),@Var6 nvarchar(36),@Var7 nvarchar(36),@Var8 nvarchar(36),@Var9 nvarchar(8),@Var10 nvarchar(8),@Var12 nvarchar(9),@Var11 nvarchar(8),@Var13 decimal(5,2),@Var14 uniqueidentifier)
                                        SELECT ID1, Val1,CASE WHEN Date1 is NULL then Date2 ELSE Date1 END as displayDate, Date2, Val2,Val0,Val3,Val4, Val5, Val6, Val7, Val8, Val9, isnull(Val10,0) as Val10, isnull(Val11,0) as Val11, #TempTable1.Val12 Val12, '' as Val13,   
                                            table1.* , Val14, Val15 as Val15   
                                            ,substring(convert(varchar(36),ID1),0,23) as TransID, substring(convert(varchar(36),val   </inputbuf>
  </process>
  <process id="process21a00a43c28" waittime="2874" schedulerid="16" kpid="2816" status="suspended" spid="147" sbid="2" ecid="0" priority="0" trancount="0" lastbatchstarted="2024-01-12T10:19:32.817" lastbatchcompleted="2024-01-12T10:19:31.813" lastattention="1900-01-01T00:00:00.813" clientapp=".Net SqlClient Data Provider" hostname="HOSTMACH1" hostpid="11172" loginname="DOMAIN1\Account1" isolationlevel="read committed (2)" xactid="25719004" currentdb="6" currentdbname="TestDB1" lockTimeout="4294967295" clientoption1="671088928" clientoption2="128056">
   <executionStack>
    <frame procname="adhoc" line="2" stmtstart="838" stmtend="6934" sqlhandle="0x020000008e6ea223919a9751bfa1ae026e9f70a4edb236af0000000000000000000000000000000000000000">
unknown    </frame>
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
(@Var0 nvarchar(36),@Var1 nvarchar(36),@Var2 nvarchar(36),@Var3 nvarchar(36),@Var4 nvarchar(36),@Var5 nvarchar(36),@Var6 nvarchar(36),@Var7 nvarchar(36),@Var8 nvarchar(36),@Var9 nvarchar(8),@Var10 nvarchar(8),@Var12 nvarchar(9),@Var11 nvarchar(8),@Var13 decimal(5,2),@Var14 uniqueidentifier)
                                        SELECT ID1, Val1,CASE WHEN Date1 is NULL then Date2 ELSE Date1 END as displayDate, Date2, Val2,Val0,Val3,Val4, Val5, Val6, Val7, Val8, Val9, isnull(Val10,0) as Val10, isnull(Val11,0) as Val11, #TempTable1.Val12 Val12, '' as Val13,   
                                            table1.* , Val14, Val15 as Val15   
                                            ,substring(convert(varchar(36),ID1),0,23) as TransID, substring(convert(varchar(36),val   </inputbuf>
  </process>
 </process-list>
 <resource-list>
  <objectlock lockPartition="0" objid="-1346206128" subresource="FULL" dbid="2" objectname="tempdb.dbo.#TempTable1__________________________________________________________________________________________________________00000000469C" id="lock217a1a7a080" mode="X" associatedObjectId="-1346206128">
   <owner-list>
    <owner id="process21a00a43c28" mode="X" />
   </owner-list>
   <waiter-list>
    <waiter id="process21a00a2b848" mode="X" requestType="wait" />
   </waiter-list>
  </objectlock>
  <TransactionMutex>
   <TransactionInfo Workspace="2308500986304" />
   <owner-list>
    <owner id="process21a00a2b848" />
   </owner-list>
   <waiter-list>
    <waiter id="process21a00a43c28" />
   </waiter-list>
  </TransactionMutex>
 </resource-list>
</deadlock>
c# sql-server-2019 database-deadlocks tempdb
1个回答
1
投票

此问题已通过将 SQL Server 2019 更新到最新的累积更新来解决。 SQL Server 错误可能导致该问题并在更新后得到解决。

仅供参考,它似乎已在 CU 19 中解决:https://learn.microsoft.com/en-us/troubleshoot/sql/releases/sqlserver-2019/cumulativeupdate19#2162840

© www.soinside.com 2019 - 2024. All rights reserved.