我有一個應用程式,它使用 SQL 事務來更新 SQL Server 上的 msdb 資料庫。該交易以不規則的時間間隔定期執行。使用 SQL Server 2012 (SP4)。過了一會兒,SQL Server 報告 msdb.dbo.backupset 表上的死鎖,唯一的參與者是執行提到的 SQL 事務的行程
下面是事務的功能示例,將引數替換為示例值,以便可以在 msdb 上輕松執行。應用程式在每次呼叫事務時傳遞新引數。
BEGIN TRAN UpdateMediaTables
DECLARE @SqlVersion int
DECLARE @LogDevName nvarchar(512)
DECLARE @MediaSetId int
DECLARE @FamilySequenceNumber tinyint
DECLARE @MaxFamilySequence tinyint
DECLARE @Mirror tinyint
DECLARE @BackupFileName nvarchar(1024)
DECLARE @BackupFileNumber int
DECLARE @MediaFamilyCount int
DECLARE @MirrorCount int
DECLARE @CompressedSize numeric(20, 0)
DECLARE @sql as nvarchar(4000)
SET @SqlVersion = @@microsoftversion / 0x1000000
SET @MediaSetId = 3498233
SET @BackupFileNumber = 1
SET @MediaFamilyCount = 1
SET @MirrorCount = 1
SET @CompressedSize = 378880
SELECT @LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = @BackupFileName
SET @sql = N'UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount'
IF @SqlVersion > 9 -- 2008
BEGIN
SET @sql = @sql N', compressed_backup_size = @CompressedSize'
END
SET @sql = @sql N' FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId'
EXEC sp_executesql @sql, N'@MediaFamilyCount int, @BackupFileNumber int, @CompressedSize numeric(20, 0), @MediaSetId int', @BackupFileNumber = @BackupFileNumber,@MediaFamilyCount = @MediaFamilyCount, @CompressedSize = @CompressedSize, @MediaSetId = @MediaSetId
UPDATE bms
SET media_family_count = @MediaFamilyCount, mirror_count = @MirrorCount
FROM msdb..backupmediaset AS bms
WHERE media_set_id = @MediaSetId
-- All bmf's
SET @FamilySequenceNumber = 1
SET @BackupFileName = N'\\testcase\Test_TLog_20211121180001.trn'
SET @Mirror = 0
UPDATE bmf
SET bmf.physical_device_name = @BackupFileName
FROM msdb..backupmediafamily AS bmf
WHERE bmf.media_set_id = @MediaSetId
AND bmf.family_sequence_number = @FamilySequenceNumber
AND bmf.mirror = @Mirror
UPDATE bmf
SET bmf.logical_device_name = @LogDevName
FROM msdb..backupmediafamily AS bmf
WHERE bmf.media_set_id = @MediaSetId
AND bmf.family_sequence_number = @FamilySequenceNumber
AND bmf.mirror = @Mirror
SET @MaxFamilySequence = 1
DELETE FROM msdb..backupmediafamily WITH (ROWLOCK)
WHERE media_set_id = @MediaSetId AND family_sequence_number > @MaxFamilySequence
COMMIT TRAN UpdateMediaTables
這是死鎖圖的 xml:
<deadlock>
<victim-list>
<victimProcess id="process2d890c8"/>
</victim-list>
<process-list>
<process id="process2d890c8" taskpriority="-5" logused="0" waitresource="PAGE: 4:1:8623 " waittime="1550" ownerId="1566457106" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:05.697" XDES="0xb16d09b80" lockMode="U" schedulerid="8" kpid="19856" status="suspended" spid="488" sbid="0" ecid="5" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:05.660" lastbatchcompleted="2021-12-21T15:00:05.633" lastattention="1900-01-01T00:00:00.633" clientapp="Demo" hostname="AA-SQL1" hostpid="14200" isolationlevel="read uncommitted (1)" xactid="1566457106" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount, compressed_backup_size = @CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a5af092360e1ef5edb55dab1b8cfba609a9b02e50000000000000000000000000000000000000000">
EXEC sp_executesql @sql, N'@MediaFamilyCount int, @BackupFileNumber int, @CompressedSize numeric(20, 0), @MediaSetId int', @BackupFileNumber = @BackupFileNumber,@MediaFamilyCount = @MediaFamilyCount, @CompressedSize = @CompressedSize, @MediaSetId = @MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE @SqlVersion int
DECLARE @LogDevName nvarchar(512)
DECLARE @MediaSetId int
DECLARE @FamilySequenceNumber tinyint
DECLARE @MaxFamilySequence tinyint
DECLARE @Mirror tinyint
DECLARE @BackupFileName nvarchar(1024)
DECLARE @BackupFileNumber int
DECLARE @MediaFamilyCount int
DECLARE @MirrorCount int
DECLARE @CompressedSize numeric(20, 0)
DECLARE @sql as nvarchar(4000)
SET @SqlVersion = @@microsoftversion / 0x1000000
SET @MediaSetId = 566952
SET @BackupFileNumber = 1
SET @MediaFamilyCount = 1
SET @MirrorCount = 1
SET @CompressedSize = 156160
SELECT @LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = @BackupFileName
SET @sql = N'UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount'
IF @SqlVersion > 9 -- 2008
BEGIN
SET @sql = @sql N', compressed_backup_size = @CompressedSize'
END
SET @sql = @sql N' FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId'
EXEC sp_executesql @sql, </inputbuf>
</process>
<process id="process2daa928" taskpriority="-5" logused="0" waitresource="PAGE: 4:1:9263 " waittime="1550" ownerId="1566457106" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:05.697" XDES="0x14b82acbd0" lockMode="U" schedulerid="1" kpid="8248" status="suspended" spid="488" sbid="0" ecid="6" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:05.660" lastbatchcompleted="2021-12-21T15:00:05.633" lastattention="1900-01-01T00:00:00.633" clientapp="Demo" hostname="AA-SQL1" hostpid="14200" isolationlevel="read uncommitted (1)" xactid="1566457106" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount, compressed_backup_size = @CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a5af092360e1ef5edb55dab1b8cfba609a9b02e50000000000000000000000000000000000000000">
EXEC sp_executesql @sql, N'@MediaFamilyCount int, @BackupFileNumber int, @CompressedSize numeric(20, 0), @MediaSetId int', @BackupFileNumber = @BackupFileNumber,@MediaFamilyCount = @MediaFamilyCount, @CompressedSize = @CompressedSize, @MediaSetId = @MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE @SqlVersion int
DECLARE @LogDevName nvarchar(512)
DECLARE @MediaSetId int
DECLARE @FamilySequenceNumber tinyint
DECLARE @MaxFamilySequence tinyint
DECLARE @Mirror tinyint
DECLARE @BackupFileName nvarchar(1024)
DECLARE @BackupFileNumber int
DECLARE @MediaFamilyCount int
DECLARE @MirrorCount int
DECLARE @CompressedSize numeric(20, 0)
DECLARE @sql as nvarchar(4000)
SET @SqlVersion = @@microsoftversion / 0x1000000
SET @MediaSetId = 566952
SET @BackupFileNumber = 1
SET @MediaFamilyCount = 1
SET @MirrorCount = 1
SET @CompressedSize = 156160
SELECT @LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = @BackupFileName
SET @sql = N'UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount'
IF @SqlVersion > 9 -- 2008
BEGIN
SET @sql = @sql N', compressed_backup_size = @CompressedSize'
END
SET @sql = @sql N' FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId'
EXEC sp_executesql @sql, </inputbuf>
</process>
<process id="process2bb4558" taskpriority="-5" logused="328" waitresource="PAGE: 4:1:9263 " waittime="948" ownerId="1566456428" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:04.410" XDES="0x14981ffb80" lockMode="U" schedulerid="7" kpid="19408" status="suspended" spid="470" sbid="0" ecid="7" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:04.393" lastbatchcompleted="2021-12-21T15:00:04.393" lastattention="1900-01-01T00:00:00.393" clientapp="Demo" hostname="AA-SQL1" hostpid="14732" isolationlevel="read uncommitted (1)" xactid="1566456428" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount, compressed_backup_size = @CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a9093d2c0a0d22ed2f73dc20e182fd1d912553b10000000000000000000000000000000000000000">
EXEC sp_executesql @sql, N'@MediaFamilyCount int, @BackupFileNumber int, @CompressedSize numeric(20, 0), @MediaSetId int', @BackupFileNumber = @BackupFileNumber,@MediaFamilyCount = @MediaFamilyCount, @CompressedSize = @CompressedSize, @MediaSetId = @MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE @SqlVersion int
DECLARE @LogDevName nvarchar(512)
DECLARE @MediaSetId int
DECLARE @FamilySequenceNumber tinyint
DECLARE @MaxFamilySequence tinyint
DECLARE @Mirror tinyint
DECLARE @BackupFileName nvarchar(1024)
DECLARE @BackupFileNumber int
DECLARE @MediaFamilyCount int
DECLARE @MirrorCount int
DECLARE @CompressedSize numeric(20, 0)
DECLARE @sql as nvarchar(4000)
SET @SqlVersion = @@microsoftversion / 0x1000000
SET @MediaSetId = 566948
SET @BackupFileNumber = 1
SET @MediaFamilyCount = 1
SET @MirrorCount = 1
SET @CompressedSize = 259072
SELECT @LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = @BackupFileName
SET @sql = N'UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount'
IF @SqlVersion > 9 -- 2008
BEGIN
SET @sql = @sql N', compressed_backup_size = @CompressedSize'
END
SET @sql = @sql N' FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId'
EXEC sp_executesql @sql, </inputbuf>
</process>
<process id="process2daacf8" taskpriority="-5" logused="328" waitresource="PAGE: 4:1:8623 " waittime="972" ownerId="1566456428" transactionname="UpdateMediaTables" lasttranstarted="2021-12-21T15:00:04.410" XDES="0x14b82ace80" lockMode="U" schedulerid="1" kpid="7048" status="suspended" spid="470" sbid="0" ecid="4" priority="5" trancount="0" lastbatchstarted="2021-12-21T15:00:04.393" lastbatchcompleted="2021-12-21T15:00:04.393" lastattention="1900-01-01T00:00:00.393" clientapp="Demo" hostname="AA-SQL1" hostpid="14732" isolationlevel="read uncommitted (1)" xactid="1566456428" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount, compressed_backup_size = @CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a9093d2c0a0d22ed2f73dc20e182fd1d912553b10000000000000000000000000000000000000000">
EXEC sp_executesql @sql, N'@MediaFamilyCount int, @BackupFileNumber int, @CompressedSize numeric(20, 0), @MediaSetId int', @BackupFileNumber = @BackupFileNumber,@MediaFamilyCount = @MediaFamilyCount, @CompressedSize = @CompressedSize, @MediaSetId = @MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE @SqlVersion int
DECLARE @LogDevName nvarchar(512)
DECLARE @MediaSetId int
DECLARE @FamilySequenceNumber tinyint
DECLARE @MaxFamilySequence tinyint
DECLARE @Mirror tinyint
DECLARE @BackupFileName nvarchar(1024)
DECLARE @BackupFileNumber int
DECLARE @MediaFamilyCount int
DECLARE @MirrorCount int
DECLARE @CompressedSize numeric(20, 0)
DECLARE @sql as nvarchar(4000)
SET @SqlVersion = @@microsoftversion / 0x1000000
SET @MediaSetId = 566948
SET @BackupFileNumber = 1
SET @MediaFamilyCount = 1
SET @MirrorCount = 1
SET @CompressedSize = 259072
SELECT @LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = @BackupFileName
SET @sql = N'UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount'
IF @SqlVersion > 9 -- 2008
BEGIN
SET @sql = @sql N', compressed_backup_size = @CompressedSize'
END
SET @sql = @sql N' FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId'
EXEC sp_executesql @sql, </inputbuf>
</process>
<process id="process12ee786188" taskpriority="-5" logused="10000" waittime="730" schedulerid="12" kpid="1808" status="suspended" spid="470" sbid="0" ecid="0" priority="5" trancount="2" lastbatchstarted="2021-12-21T15:00:04.393" lastbatchcompleted="2021-12-21T15:00:04.393" lastattention="1900-01-01T00:00:00.393" clientapp="Demo" hostname="AA-SQL1" hostpid="14732" loginname="DEMO\test" isolationlevel="read uncommitted (1)" xactid="1566456428" currentdb="1" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="190" sqlhandle="0x020000000aac851a57d841f58dc63ba4bbe4b4059b68c6ab0000000000000000000000000000000000000000">
UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount, compressed_backup_size = @CompressedSize FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId </frame>
<frame procname="mssqlsystemresource.sys.sp_executesql" line="1" stmtstart="-1" sqlhandle="0x0400ff7f427f99d9010000000000000000000000000000000000000000000000000000000000000000000000">
sp_executesql </frame>
<frame procname="adhoc" line="36" stmtstart="1996" stmtend="2528" sqlhandle="0x02000000a9093d2c0a0d22ed2f73dc20e182fd1d912553b10000000000000000000000000000000000000000">
EXEC sp_executesql @sql, N'@MediaFamilyCount int, @BackupFileNumber int, @CompressedSize numeric(20, 0), @MediaSetId int', @BackupFileNumber = @BackupFileNumber,@MediaFamilyCount = @MediaFamilyCount, @CompressedSize = @CompressedSize, @MediaSetId = @MediaSetId </frame>
</executionStack>
<inputbuf>
BEGIN TRAN UpdateMediaTables
DECLARE @SqlVersion int
DECLARE @LogDevName nvarchar(512)
DECLARE @MediaSetId int
DECLARE @FamilySequenceNumber tinyint
DECLARE @MaxFamilySequence tinyint
DECLARE @Mirror tinyint
DECLARE @BackupFileName nvarchar(1024)
DECLARE @BackupFileNumber int
DECLARE @MediaFamilyCount int
DECLARE @MirrorCount int
DECLARE @CompressedSize numeric(20, 0)
DECLARE @sql as nvarchar(4000)
SET @SqlVersion = @@microsoftversion / 0x1000000
SET @MediaSetId = 566948
SET @BackupFileNumber = 1
SET @MediaFamilyCount = 1
SET @MirrorCount = 1
SET @CompressedSize = 259072
SELECT @LogDevName = name
FROM master..sysdevices AS sdev
WHERE phyname = @BackupFileName
SET @sql = N'UPDATE bs SET position = @BackupFileNumber, last_family_number = @MediaFamilyCount'
IF @SqlVersion > 9 -- 2008
BEGIN
SET @sql = @sql N', compressed_backup_size = @CompressedSize'
END
SET @sql = @sql N' FROM msdb..backupset AS bs
WHERE media_set_id = @MediaSetId'
EXEC sp_executesql @sql, </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="8623" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lock5e1d530780" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process12ee786188" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process2d890c8" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="9263" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lockf1b4c0980" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process12ee786188" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process2daa928" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="9263" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lockf1b4c0980" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process2daa928" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process2bb4558" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="8623" dbid="4" subresource="FULL" objectname="msdb.dbo.backupset" id="lock5e1d530780" mode="U" associatedObjectId="72057594045595648">
<owner-list>
<owner id="process2d890c8" mode="U" requestType="wait"/>
</owner-list>
<waiter-list>
<waiter id="process2daacf8" mode="U" requestType="wait"/>
</waiter-list>
</pagelock>
<exchangeEvent id="Pipe25c250400" WaitType="e_waitPipeGetRow" nodeId="2">
<owner-list>
<owner id="process2daacf8"/>
<owner id="process2bb4558"/>
</owner-list>
<waiter-list>
<waiter id="process12ee786188"/>
</waiter-list>
</exchangeEvent>
</resource-list>
</deadlock>

I don't see how this situation could lead to a deadlock. Even if the two processes coincide in parallel, the two transactions are identical and therefore execute their queries in the same sequential order. Furthermore, the query that updates the backupset table doesn't have who to deadlock with, since it is the only one in the entire transaction that queries this table. Lock yes, but not deadlock. Can someone please help me understand how this deadlock situation is possible?
uj5u.com熱心網友回復:
而不是診斷這個,我只是點擊“簡單按鈕”,并使用應用程式鎖序列化事務:
BEGIN TRAN UpdateMediaTables
exec sp_getapplock 'UpdateMediaTables', 'Exclusive'
. . .
然后第二個會話將在獲取任何鎖之前被阻塞,直到第一個會話完成。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/393006.html
