|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
Привожу файл графа дэдлока (он небольшой), вот та же инфа в XML: <deadlock> <victim-list> <victimProcess id="process1e08743848" /> <victimProcess id="process8bb66cca8" /> </victim-list> <process-list> <process id="process1e08743848" taskpriority="0" logused="0" waitresource="KEY: 6:72057594043301888 (975922a7848b)" waittime="1632" ownerId="2391059109" transactionname="user_transaction" lasttranstarted="2021-04-02T12:35:07.783" XDES="0xe30748970" lockMode="U" schedulerid="8" kpid="39844" status="suspended" spid="93" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-04-02T12:35:07.783" lastbatchcompleted="2021-04-02T12:35:07.783" lastattention="1900-01-01T00:00:00.783" clientapp="Report Server" hostname="SL01537" hostpid="24252" loginname="NT SERVICE\ReportServer" isolationlevel="read committed (2)" xactid="2391059109" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> <executionStack> <frame procname="ReportServer.dbo.DereferenceSessionSnapshot" line="16" stmtstart="752" stmtend="1302" sqlhandle="0x030005001c5c8438b3fb3201d4a6000001000000000000000000000000000000000000000000000000000000"> UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM [ReportServerTempDB].dbo.SnapshotData AS SN INNER JOIN [ReportServerTempDB].dbo.SessionData AS SE ON SN.SnapshotDataID = SE.SnapshotDataID WHERE SE.SessionID = @SessionID AND SE.OwnerID = @OwnerI </frame> <frame procname="ReportServer.dbo.ClearSessionSnapshot" line="13" stmtstart="590" stmtend="700" sqlhandle="0x0300050056c60d42c0fb3201d4a6000001000000000000000000000000000000000000000000000000000000"> EXEC DereferenceSessionSnapshot @SessionID, @OwnerID </frame> </executionStack> <inputbuf> Proc [Database Id = 5 Object Id = 1108198998] </inputbuf> </process> <process id="process8bb66cca8" taskpriority="0" logused="0" waitresource="KEY: 6:72057594043301888 (975922a7848b)" waittime="1632" ownerId="2391059218" transactionname="user_transaction" lasttranstarted="2021-04-02T12:35:07.843" XDES="0x2d9191a040" lockMode="U" schedulerid="1" kpid="22812" status="suspended" spid="77" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-04-02T12:35:07.843" lastbatchcompleted="2021-04-02T12:35:07.843" lastattention="1900-01-01T00:00:00.843" clientapp="Report Server" hostname="SL01537" hostpid="24252" loginname="NT SERVICE\ReportServer" isolationlevel="read committed (2)" xactid="2391059218" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> <executionStack> <frame procname="ReportServer.dbo.DereferenceSessionSnapshot" line="16" stmtstart="752" stmtend="1302" sqlhandle="0x030005001c5c8438b3fb3201d4a6000001000000000000000000000000000000000000000000000000000000"> UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM [ReportServerTempDB].dbo.SnapshotData AS SN INNER JOIN [ReportServerTempDB].dbo.SessionData AS SE ON SN.SnapshotDataID = SE.SnapshotDataID WHERE SE.SessionID = @SessionID AND SE.OwnerID = @OwnerI </frame> <frame procname="ReportServer.dbo.ClearSessionSnapshot" line="13" stmtstart="590" stmtend="700" sqlhandle="0x0300050056c60d42c0fb3201d4a6000001000000000000000000000000000000000000000000000000000000"> EXEC DereferenceSessionSnapshot @SessionID, @OwnerID </frame> </executionStack> <inputbuf> Proc [Database Id = 5 Object Id = 1108198998] </inputbuf> </process> <process id="process22a01908c8" taskpriority="0" logused="592" waitresource="KEY: 6:72057594040745984 (aed6c0e5137d)" waittime="1632" ownerId="2391059166" transactionname="user_transaction" lasttranstarted="2021-04-02T12:35:07.810" XDES="0x19c62630a0" lockMode="X" schedulerid="2" kpid="38184" status="suspended" spid="73" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2021-04-02T12:35:07.810" lastbatchcompleted="2021-04-02T12:35:07.810" lastattention="1900-01-01T00:00:00.810" clientapp="Report Server" hostname="SL01537" hostpid="24252" loginname="NT SERVICE\ReportServer" isolationlevel="read committed (2)" xactid="2391059166" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> <executionStack> <frame procname="ReportServer.dbo.ClearSessionSnapshot" line="15" stmtstart="702" stmtend="1426" sqlhandle="0x0300050056c60d42c0fb3201d4a6000001000000000000000000000000000000000000000000000000000000"> UPDATE SE SET SE.SnapshotDataID = null, SE.IsPermanentSnapshot = null, SE.SnapshotExpirationDate = null, SE.ShowHideInfo = null, SE.HasInteractivity = null, SE.AutoRefreshSeconds = null, SE.Expiration = @Expiration FROM [ReportServerTempDB].dbo.SessionData AS SE WHERE SE.SessionID = @SessionID AND SE.OwnerID = @OwnerI </frame> </executionStack> <inputbuf> Proc [Database Id = 5 Object Id = 1108198998] </inputbuf> </process> </process-list> <resource-list> <keylock hobtid="72057594043301888" dbid="6" objectname="ReportServerTempDB.dbo.SnapshotData" indexname="IX_SnapshotData" id="lock2a9c434800" mode="X" associatedObjectId="72057594043301888"> <owner-list> <owner id="process8bb66cca8" mode="U" requestType="wait" /> </owner-list> <waiter-list> <waiter id="process1e08743848" mode="U" requestType="wait" /> </waiter-list> </keylock> <keylock hobtid="72057594043301888" dbid="6" objectname="ReportServerTempDB.dbo.SnapshotData" indexname="IX_SnapshotData" id="lock2a9c434800" mode="X" associatedObjectId="72057594043301888"> <owner-list> <owner id="process22a01908c8" mode="X" /> </owner-list> <waiter-list> <waiter id="process8bb66cca8" mode="U" requestType="wait" /> </waiter-list> </keylock> <keylock hobtid="72057594040745984" dbid="6" objectname="ReportServerTempDB.dbo.SessionData" indexname="IDX_SessionData" id="lock2baca83f00" mode="U" associatedObjectId="72057594040745984"> <owner-list> <owner id="process1e08743848" mode="S" /> </owner-list> <waiter-list> <waiter id="process22a01908c8" mode="X" requestType="convert" /> </waiter-list> </keylock> </resource-list> </deadlock> и вот тексты двух маленьких процедур, которые там в <executionStack>: CREATE PROCEDURE [dbo].[ClearSessionSnapshot] @SessionID as varchar(32), @OwnerSid as varbinary(85) = NULL, @OwnerName as nvarchar(260), @AuthType as int, @Expiration as datetime AS DECLARE @OwnerID uniqueidentifier EXEC GetUserID @OwnerSid, @OwnerName, @AuthType, @OwnerID OUTPUT EXEC DereferenceSessionSnapshot @SessionID, @OwnerID UPDATE SE SET SE.SnapshotDataID = null, SE.IsPermanentSnapshot = null, SE.SnapshotExpirationDate = null, SE.ShowHideInfo = null, SE.HasInteractivity = null, SE.AutoRefreshSeconds = null, SE.Expiration = @Expiration FROM [ReportServerTempDB].dbo.SessionData AS SE WHERE SE.SessionID = @SessionID AND SE.OwnerID = @OwnerID ----------------------------------------------------------------------------------------------- CREATE PROCEDURE [dbo].[DereferenceSessionSnapshot] @SessionID as varchar(32), @OwnerID as uniqueidentifier AS UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM SnapshotData AS SN INNER JOIN [ReportServerTempDB].dbo.SessionData AS SE ON SN.SnapshotDataID = SE.SnapshotDataID WHERE SE.SessionID = @SessionID AND SE.OwnerID = @OwnerID UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM [ReportServerTempDB].dbo.SnapshotData AS SN INNER JOIN [ReportServerTempDB].dbo.SessionData AS SE ON SN.SnapshotDataID = SE.SnapshotDataID WHERE SE.SessionID = @SessionID AND SE.OwnerID = @OwnerID ----------------------------------------------------------------------------------------------- структуры таблиц с индексами: CREATE TABLE [dbo].[SessionData]( [SessionID] [varchar](32) NOT NULL, [CompiledDefinition] [uniqueidentifier] NULL, [SnapshotDataID] [uniqueidentifier] NULL, [IsPermanentSnapshot] [bit] NULL, [ReportPath] [nvarchar](464) NULL, [Timeout] [int] NOT NULL, [AutoRefreshSeconds] [int] NULL, [Expiration] [datetime] NOT NULL, [ShowHideInfo] [image] NULL, [DataSourceInfo] [image] NULL, [OwnerID] [uniqueidentifier] NOT NULL, [EffectiveParams] [ntext] NULL, [CreationTime] [datetime] NOT NULL, [HasInteractivity] [bit] NULL, [SnapshotExpirationDate] [datetime] NULL, [HistoryDate] [datetime] NULL, [PageHeight] [float] NULL, [PageWidth] [float] NULL, [TopMargin] [float] NULL, [BottomMargin] [float] NULL, [LeftMargin] [float] NULL, [RightMargin] [float] NULL, [AwaitingFirstExecution] [bit] NULL, [EditSessionID] [varchar](32) NULL, [DataSetInfo] [varbinary](max) NULL, [SitePath] [nvarchar](440) NULL, [SiteZone] [int] NOT NULL, [ReportDefinitionPath] [nvarchar](464) NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO CREATE UNIQUE CLUSTERED INDEX [IDX_SessionData] ON [dbo].[SessionData] ( [SessionID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_EditSessionID] ON [dbo].[SessionData] ( [EditSessionID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_SessionCleanup] ON [dbo].[SessionData] ( [Expiration] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_SessionSnapshotID] ON [dbo].[SessionData] ( [SnapshotDataID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO ALTER TABLE [dbo].[SessionData] ADD DEFAULT ((0)) FOR [SiteZone] GO -------------------------------------------------------------------------- CREATE TABLE [dbo].[SnapshotData]( [SnapshotDataID] [uniqueidentifier] NOT NULL, [CreatedDate] [datetime] NOT NULL, [ParamsHash] [int] NULL, [QueryParams] [ntext] NULL, [EffectiveParams] [ntext] NULL, [Description] [nvarchar](512) NULL, [DependsOnUser] [bit] NULL, [PermanentRefcount] [int] NOT NULL, [TransientRefcount] [int] NOT NULL, [ExpirationDate] [datetime] NOT NULL, [PageCount] [int] NULL, [HasDocMap] [bit] NULL, [Machine] [nvarchar](512) NOT NULL, [PaginationMode] [smallint] NULL, [ProcessingFlags] [int] NULL, [IsCached] [bit] NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO CREATE CLUSTERED INDEX [IX_SnapshotData] ON [dbo].[SnapshotData] ( [SnapshotDataID] ASC, [ParamsHash] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IS_SnapshotExpiration] ON [dbo].[SnapshotData] ( [PermanentRefcount] ASC, [ExpirationDate] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_SnapshotCleaning] ON [dbo].[SnapshotData] ( [PermanentRefcount] ASC, [TransientRefcount] ASC ) INCLUDE ( [Machine]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO ALTER TABLE [dbo].[SnapshotData] ADD DEFAULT ((0)) FOR [IsCached] GO Поясните, плиз, как могут здесь появляться такие блокировки, почему например spid 93 держит U-lock на IDX_SessionData ? spid 73 не отпускает X-lock на IX_SnapshotData, п.ч. всё выполняется в какой-то внешней транзакции ? И почему в дэдлоке две жертвы ? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2021, 11:41 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
sps777 почему например spid 93 держит U-lock на IDX_SessionData ? И ждет U на IX_SnapshotData. sps777 spid 73 не отпускает X-lock на IX_SnapshotData sps777 И почему в дэдлоке две жертвы ? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2021, 21:41 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
invm sps777 почему например spid 93 держит U-lock на IDX_SessionData ? Тогда что означает mode="U" в <keylock> (в спойлере), кто его держит ? <keylock hobtid="72057594040745984" dbid="6" objectname="ReportServerTempDB.dbo.SessionData" indexname="IDX_SessionData" id="lock2baca83f00" mode="U" associatedObjectId="72057594040745984"> <owner-list> <owner id="process1e08743848" mode="S" /> </owner-list> <waiter-list> <waiter id="process22a01908c8" mode="X" requestType="convert" /> </waiter-list> </keylock> invm sps777 spid 73 не отпускает X-lock на IX_SnapshotData invm sps777 И почему в дэдлоке две жертвы ? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2021, 23:05 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
sps777, уберите вот это INNER JOIN [ReportServerTempDB].dbo.SessionData AS SE ON SN.SnapshotDataID = SE.SnapshotDataID из update, замените на временную таблицу или включите RCSI. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2021, 23:42 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
sps777, процессы работают не по очереди, а параллельно, нет никакой гарантий - какой из них первым получит блокировку. Выжить должен только один, как в известном фильме. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2021, 23:45 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
sps777 Тогда что означает mode="U" в <keylock> (в спойлере), кто его держит ? sps777 В процедурах нет BEGIN TRAN - т.е. вызов всего этого, надо предположить, обернут в транзакцию ? sps777 Смотрю на граф - убиваем 93, 73 получает свой "Request Mode" и освобождает свой "Owner Mode" и, после этого, 77 так же получает свой "Request Mode" и освобождает свой "Owner Mode". Почему так не работает ? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 11:24 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
sps777, тут вот что странно, последовательность запуска была такой: processnamespidprocess1e0874384893process8bb66cca8 77process22a01908c8 73 rn spid event start_time tran_id1 93 ReportServer.dbo.DereferenceSessionSnapshot 2021-04-02T12:35:07.783 23910591092 73 ReportServer.dbo.ClearSessionSnapshot 2021-04-02T12:35:07.810 23910591663 77 ReportServer.dbo.ClearSessionSnapshot 2021-04-02T12:35:07.843 2391059218 то есть по последовательности инструкций должна была получаться схема (я предположу что ReportServer неявно открывает пользовательскую транзакцию, и блокировки будут удерживаться) rn spid stmt lock_object lock_resource lock_mode waits1 93 exec [dbo].[DereferenceSessionSnapshot]2 93 /* UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM SnapshotData AS SN */ [SnapshotData] (keylock: IX_SnapshotData) U2* 93 /* UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM SnapshotData AS SN */ [ReportServerTempDB].dbo.SessionData (keylock: IDX_SessionData) S2** 93 /* UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM SnapshotData AS SN */ [SnapshotData] (keylock: IX_SnapshotData) convert U->X3 93 вот на этом этапе интересная ситуация: сессия в режиме изоляции READ COMMITTED U блокировка должна по сути сконвертироваться в X и остаться до окончания транзакции а S сняться после получения3* 93 на этом этапе мы видим ситуацию из графа дедлока. только здесь у 93 сессии еще должна быть S блокировка на ключ ReportServerTempDB.SessionData которого начинает ожидать сессия 7777 waits 935 93 /* UPDATE SN SET TransientRefcount = TransientRefcount - 1 FROM [ReportServerTempDB].dbo.SnapshotData AS SN */ [ReportServerTempDB].dbo.SnapshotData (keylock: IX_SnapshotData) U 93 waits 73 другие сессии не расписывал, они начинают получать свои локи приблизительно одновременно с шагом 2. явную последовательность получения блокировок далабы xEvent-сессия. но что мне больше всего интересно как получается так что 93 держит S и в тоже время начинает ждать у от второй инструкции апдейта процедуры add: АААА все я Вася! сейчас на процу глянул и понял что не туда смотрел. там S блокировка не от первого апдейта а от второго. Код: sql 1. 2. 3. 4. 5.
тогда все вполне логично add2: тогда единственное что меня еще тут смущает в целом структура индексов выстроенна так что коллизий блокировок по ключам быть не должно. получается что у ТС 3 сессии пытались грохнуть (судя по названию процедур) одну и туже сущность иначе бы дедлока не было ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 15:52 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
felix_ff предположу что ReportServer неявно открывает пользовательскую транзакцию, и блокировки будут удерживаться Да, я бы тоже это предположил - на графе spid_73 не может же держать свой "Owner Mode: X" на IX_SnapshotData, если у него текущая инструкция - это update только по табл.SessionData. Значит держит своими предыдущими инструкциями в где-то открытой до этого транзакции. Пытаться всё представить в хронологии - это прямо глубоко ). Видно, что несмотря на то что 93 стартовал 1-ым, 73 его легко обошел и 1-ым достиг последней инструкции в батче (update se). В табличке с 6-ю столбцами кажется перепутаны 77 и 73, но не суть. felix_ff add2: тогда единственное что меня еще тут смущает в целом структура индексов выстроенна так что коллизий блокировок по ключам быть не должно. получается что у ТС 3 сессии пытались грохнуть (судя по названию процедур) одну и туже сущность иначе бы дедлока не было что одни и те же сущности - наверное не обязательно даже индексы анализировать, что сам тип блокировки "keylock" это ж тоже об этом говорит. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 21:51 |
|
Дэдлок писателей в БД ReportServerTempDB
|
|||
---|---|---|---|
#18+
sps777 felix_ff предположу что ReportServer неявно открывает пользовательскую транзакцию, и блокировки будут удерживаться Да, я бы тоже это предположил - на графе spid_73 не может же держать свой "Owner Mode: X" на IX_SnapshotData, если у него текущая инструкция - это update только по табл.SessionData. Значит держит своими предыдущими инструкциями в где-то открытой до этого транзакции. Пытаться всё представить в хронологии - это прямо глубоко ). Видно, что несмотря на то что 93 стартовал 1-ым, 73 его легко обошел и 1-ым достиг последней инструкции в батче (update se). В табличке с 6-ю столбцами кажется перепутаны 77 и 73, но не суть. да там перепутал. что одни и те же сущности - наверное не обязательно даже индексы анализировать, что сам тип блокировки "keylock" это ж тоже об этом говорит. не совсем, у вас и при сканировании индексов будут теже блокировки по ключам если не будет укрупнений. поэтому здесь важно понимать дают ли предикаты и условия объединений одну строку или несколько. по SessionData предикат where SE.SessionID = @SessionID AND SE.OwnerID = @OwnerID однозначно установит лок только на единственный ключ, а вот предикат соединения ON SN.SnapshotDataID = SE.SnapshotDataID по сути может блокировать несколько ключей индекс там не уникальный. но у вас по большей части проблема дедлока из-за преобразования U->X в теории вам было бы достаточно несколько изменить инструкцию второго апдейта: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
или понять причины нафига несколько сессий одновременно ломатся за этой сущностью. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.04.2021, 22:18 |
|
|
start [/forum/topic.php?fid=46&fpage=26&tid=1684771]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
35ms |
get topic data: |
12ms |
get forum data: |
2ms |
get page messages: |
46ms |
get tp. blocked users: |
2ms |
others: | 313ms |
total: | 437ms |
0 / 0 |