Wir verwenden eine ASPState-Datenbank, um den .NET-Sitzungsstatus in einem SQL Server 2005-Cluster beizubehalten. In Spitzenzeiten sehen wir ein merkwürdiges Verhalten
Der DeleteExpiredSessions-Prozess wird jede Minute über einen Agentenjob ausgeführt. Manchmal dauert es viele Minuten, bis dieser Job abgelaufene Sitzungen ausgeführt und gelöscht hat
Anforderungen von der Anwendung an die ASPState-Datenbank sind sehr langsam. Ich glaube, das liegt daran, dass das DeleteExpiredSessions-Verfahren exklusive Sperren auf dem Tisch hält
Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[DeleteExpiredSessions]
AS
SET NOCOUNT ON
SET DEADLOCK_PRIORITY LOW
DECLARE @now datetime
SET @now = GETUTCDATE()
DECLARE @tblExpiredSessions TABLE
(
SessionID nvarchar(88) NOT NULL PRIMARY KEY
)
INSERT INTO @tblExpiredSessions (SessionID)
SELECT SessionID
FROM [ASPState].dbo.ASPStateTempSessions WITH (READUNCOMMITTED)
WHERE Expires < @now
--EXPIRED SESSION LOGGING
/*
DECLARE @ExpiredSessionCount Int;
SELECT @ExpiredSessionCount = COUNT(SessionID)
FROM @tblExpiredSessions;
*/
IF @@ROWCOUNT <> 0
BEGIN
DECLARE ExpiredSessionCursor CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR SELECT SessionID FROM @tblExpiredSessions ORDER BY CHECKSUM(NEWID())
DECLARE @SessionID nvarchar(88)
OPEN ExpiredSessionCursor
FETCH NEXT FROM ExpiredSessionCursor INTO @SessionID
WHILE @@FETCH_STATUS = 0
BEGIN
DELETE FROM [ASPState].dbo.ASPStateTempSessions WHERE SessionID = @SessionID AND Expires < @now
FETCH NEXT FROM ExpiredSessionCursor INTO @SessionID
END
CLOSE ExpiredSessionCursor
DEALLOCATE ExpiredSessionCursor
END
--EXPIRED SESSION LOGGING
/*
BEGIN TRY
INSERT INTO DeleteExpiredSessionLog(RunStart, RunEnd, ExpiredSessionsDeleted)
VALUES (@now, GETUTCDATE(), @ExpiredSessionCount);
END TRY
BEGIN CATCH
--SWALLOW ANY EXCEPTION
END CATCH;
*/
RETURN 0
- Die Protokolldatei füllt sich und erzwingt in einigen Fällen das automatische Wachstum, obwohl sich die Datenbank in einer einfachen Wiederherstellung befindet
Darüber hinaus werden in einer Ablaufverfolgung mehrere Anforderungen für dieselbe Sitzung schnell hintereinander angezeigt. Zum Beispiel exec dbo.TempResetTimeout @id=N'32gghltsuoesnvlzbehchp2m2014c0f1'
14 Mal in <1 Sekunde, also wundern wir uns über diese Ursache oder Überlastung, sind uns aber nicht sicher, woher dieses Verhalten stammt.
Anregungen oder Erklärungen zu diesem Verhalten sind willkommen.
quelle
SELECT 1; WHILE @@ROWCOUNT <> 0 BEGIN DELETE TOP (10) ... END
Antworten:
Ich vermute, Sie haben Gregs Ersetzungsverfahren als vorbeugende Optimierung implementiert. Der Ansatz, jeweils eine Zeile zu verwenden, beschränkt das Sperren auf eine einzelne Zeile, aber es wird viel länger dauern - insbesondere, wenn Sie SQL Server zwingen, Zeilen in zufälliger Reihenfolge anzugreifen.
Mein Vorschlag wäre, zum ursprünglichen Verfahren zurückzukehren:
Wenn Sie feststellen, dass dies aufgrund der vorgenommenen Sperren zu einem Leistungsproblem wird, können Sie dies aufteilen und sogar die Auswirkungen auf die Protokolle verringern, indem Sie Folgendes verwenden:
Dies wird meiner Meinung nach viel besser sein, als einen zufälligen Cursor zu verwenden, um jeweils eine Zeile zu löschen. Sie können den Wert
TOP (1000)
basierend auf der tatsächlichen Beobachtung anpassen .Ein paar andere Ideen, die helfen könnten:
(a) Setzen Sie das Wiederherstellungsmodell der ASPState-Datenbank auf einfach (standardmäßig auf vollständig).
(b) ändern Sie sich
ASPState_Job_DeleteExpiredSessions
, um alle 5 oder 10 Minuten anstatt jede Minute zu laufen. Wenn die Ausführung dieses Jobs> 1 Minute dauert, wird er immer ausgeführt. Hoffentlich ist es nicht vollständig linear, was bedeutet, dass das Warten von 5 Minuten anstelle von 1 nicht mehr als 5 Minuten Arbeit anstelle von 1 in die Warteschlange stellt. Die Umsetzung meiner obigen Vorschläge sollte dabei helfen.quelle