Ich habe ein paar Deadlocks auf unserem Live-Server, ich weiß, es ist scheiße.
Wie auch immer, ich versuche herauszufinden, wie ich feststellen kann, welcher SQL-Code die Sperren verursacht (oder ihn zu lange hält).
Ich habe alle Locks- Ereignisse hinzugefügt (erworben, Deadlock, Eskalation, freigegeben, Timeout usw.), aber alles, was ich sehe, ist eine Bombardierung erworbener / freigegebener Ereignisse, mit nicht viel zusätzlichen Informationen.
Ich bin mir ziemlich sicher, dass ich das "Szenario" kenne, das die Deadlocks verursacht, da wir nach einem INSERT / UPDATE / DELETE einen Trigger auf einer Tabelle haben, und dies macht eine Menge zusätzlicher Arbeit, manchmal bis zu 8 Sekunden wert.
Während des Großteils dieser zusätzlichen Arbeit werden Daten aus Tabelle A abgerufen und in eine Tabellenvariable eingefügt. Auf dieser Tabellenvariablen werden viele Arbeitsspeicher gespeichert (ca. 6 Sekunden vergehen), und schließlich erfolgt eine Einfügung in Tabelle B.
Frage: Würde das tatsächlich eine Tabellensperre für die gesamte Tabelle verursachen, obwohl ich nur bestimmte Zeilen in einer Tabellenvariablen auswähle ?
Ich habe "Trigger Tracing" hinzugefügt (in Tabelle x Werte einfügen ('hi im here') usw.) und ich weiß im Grunde, dass die Prozedur am längsten dauert (und daher wahrscheinlich die Sperre verursachen muss?)
Aber ich bin mir immer noch nicht sicher, warum der Deadlock passiert.
Frage: Ich kann sehen, dass 2 Sperreneskalationen auftreten. Bedeutet dies, dass Zeilensperren zu Tabellensperren eskaliert wurden?
Frage: Kann mir jemand Tipps geben, wie ich diesen Stillstand weiter verfolgen kann?
BEARBEITEN:
Hier ist das Deadlock-Diagramm
EDIT 2:
Hier ist der Code für [UpdatePostsCleanedUriUniqueUri], der möglicherweise eine Tabellensperre verursacht?
ALTER PROC [dbo].[UpdatePostsCleanedUriUniqueUri]
(
@PostIds IdentityType READONLY
)
AS
SET NOCOUNT ON
-- *************************************************************************
-- ******************* Create the Cleaned Uri's, first ********************
-- *************************************************************************
---- "Remove" any existing cleaned uri's, per location
UPDATE a
SET a.CleanedUri = NEWID(),
a.UniqueUri = NEWID()
FROM [dbo].[Posts] a
INNER JOIN @PostIds b ON a.PostId = b.Id
-- ** Now add the cleaned uri.
UPDATE a
SET a.CleanedUri = [dbo].[ToFixedLengthToString](
[dbo].[IsNullOrEmpty](LOWER([dbo].[ToAlphaNumericText]([Subject], '-', 1)), 'unknown'), 60, '')
FROM [dbo].[Posts] a
INNER JOIN @PostIds b ON a.PostId = b.Id
-- *************************************************************************
-- ******** Now create the Unique Uri from the cleaned one, above **********
-- *************************************************************************
-- Now Re-Add these unique uri's.
;WITH CTE AS (
SELECT DISTINCT CleanedUri
FROM [dbo].[Posts] a
INNER JOIN @PostIds b ON a.PostId = b.Id
)
UPDATE a
SET a.UniqueUri = Result.UniqueUri
FROM [dbo].[Posts] a
INNER JOIN (
SELECT SubQuery.PostId,
CASE SubQuery.RowNumber
WHEN 1 THEN SubQuery.CleanedUri
ELSE SubQuery.CleanedUri + '-' + CAST(SubQuery.RowNumber - 1 AS NVARCHAR(20)) END AS UniqueUri
FROM (
SELECT PostId, a.CleanedUri,
ROW_NUMBER() OVER (PARTITION BY a.CleanedUri ORDER BY a.CleanedUri) AS RowNumber
FROM [dbo].[Posts] a
INNER JOIN CTE b ON a.CleanedUri = b.CleanedUri
) SubQuery
) Result ON a.PostId = Result.PostId
;
Da es einen INNER JOIN hat, hätte ich gedacht, dass es nur die übereinstimmenden Zeilen sperren würde? Oder sollte ich verwenden WITH (ROWLOCK)
?
EDIT 3:
USE [XWing]
GO
/****** Object: Table [dbo].[Posts] Script Date: 02/17/2012 13:29:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Posts](
[PostId] [int] IDENTITY(1,1) NOT NULL,
[Subject] [nvarchar](300) NULL,
[CleanedUri] [nvarchar](70) NOT NULL,
[UniqueUri] [nvarchar](70) NOT NULL,
[Content] [nvarchar](max) NULL,
[Source] [nvarchar](50) NULL,
[LocationTypeId] [tinyint] NOT NULL,
[CreatedOn] [smalldatetime] NOT NULL,
[ModifiedOn] [smalldatetime] NOT NULL,
[IsEditorsChoice] [bit] NOT NULL,
[IsVisible] [bit] NOT NULL,
[UserId] [int] NOT NULL,
[LatLongPoint] [geography] NULL,
[UserLastIpAddress] [varchar](15) NULL,
[OldPostId] [int] NULL,
[OldUniqueUri] [nvarchar](250) NULL,
[ThemeId] [int] NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY CLUSTERED
(
[PostId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Posts] WITH CHECK ADD CONSTRAINT [FK_Posts_Themes] FOREIGN KEY([ThemeId])
REFERENCES [dbo].[Themes] ([ThemeId])
GO
ALTER TABLE [dbo].[Posts] CHECK CONSTRAINT [FK_Posts_Themes]
GO
ALTER TABLE [dbo].[Posts] WITH CHECK ADD CONSTRAINT [FK_Posts_Users] FOREIGN KEY([UserId])
REFERENCES [dbo].[Users] ([UserId])
GO
ALTER TABLE [dbo].[Posts] CHECK CONSTRAINT [FK_Posts_Users]
GO
ALTER TABLE [dbo].[Posts] ADD CONSTRAINT [DF_Posts_IsEditorsChoice] DEFAULT ((0)) FOR [IsEditorsChoice]
GO
ALTER TABLE [dbo].[Posts] ADD CONSTRAINT [DF_Posts_ThemeId] DEFAULT ((1)) FOR [ThemeId]
GO
USE [XWing]
GO
/****** Object: Index [IX_Posts_IsEditorsChoice_Include_PostId_LocationTypeId] Script Date: 02/17/2012 13:31:59 ******/
CREATE NONCLUSTERED INDEX [IX_Posts_IsEditorsChoice_Include_PostId_LocationTypeId] ON [dbo].[Posts]
(
[IsEditorsChoice] ASC
)
INCLUDE ( [PostId],
[LocationTypeId]) 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, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [XWing]
GO
/****** Object: Index [IX_Posts_IsVisible] Script Date: 02/17/2012 13:32:02 ******/
CREATE NONCLUSTERED INDEX [IX_Posts_IsVisible] ON [dbo].[Posts]
(
[IsVisible] 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, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [XWing]
GO
/****** Object: Index [IX_Posts_LocationTypeId] Script Date: 02/17/2012 13:32:07 ******/
CREATE NONCLUSTERED INDEX [IX_Posts_LocationTypeId] ON [dbo].[Posts]
(
[LocationTypeId] ASC
)
INCLUDE ( [PostId]) 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, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [XWing]
GO
/****** Object: Index [IX_Posts_OldPostId] Script Date: 02/17/2012 13:32:12 ******/
CREATE NONCLUSTERED INDEX [IX_Posts_OldPostId] ON [dbo].[Posts]
(
[OldPostId] 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, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [XWing]
GO
/****** Object: Index [IX_Posts_UserId] Script Date: 02/17/2012 13:32:17 ******/
CREATE NONCLUSTERED INDEX [IX_Posts_UserId] ON [dbo].[Posts]
(
[UserId] ASC
)
INCLUDE ( [PostId]) 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, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [XWing]
GO
/****** Object: Index [SX_Posts_Location] Script Date: 02/17/2012 13:32:22 ******/
CREATE SPATIAL INDEX [SX_Posts_Location] ON [dbo].[Posts]
(
[LatLongPoint]
)USING GEOGRAPHY_GRID
WITH (
GRIDS =(LEVEL_1 = LOW,LEVEL_2 = LOW,LEVEL_3 = MEDIUM,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 16, PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
USE [XWing]
GO
/****** Object: Index [UIX_Posts_UniqueUri] Script Date: 02/17/2012 13:32:41 ******/
CREATE UNIQUE NONCLUSTERED INDEX [UIX_Posts_UniqueUri] ON [dbo].[Posts]
(
[UniqueUri] 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, FILLFACTOR = 80) ON [PRIMARY]
GO
BEARBEITEN 4
Hier ist der Ausführungsplan für UpdatePostsCleanedUriUniqueUri, nachdem der folgende Index für CleanedUri hinzugefügt wurde:
CREATE NONCLUSTERED INDEX [IX_Posts_CleanedUri_Include_PostId] ON [dbo].[Posts]
(
[CleanedUri] ASC
)
INCLUDE ( [PostId]) 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