ASPState khóa cơ sở dữ liệu và các vấn đề tăng trưởng


8

Chúng tôi sử dụng cơ sở dữ liệu ASPState để duy trì trạng thái Phiên .NET trên cụm SQL Server 2005. Chúng ta đang thấy một số hành vi kỳ lạ trong thời kỳ cao điểm

  • Proc DeleteExpiredSments được chạy mỗi phút thông qua một công việc đại lý. Đôi khi công việc này mất nhiều phút để chạy và xóa các phiên hết hạn

  • Yêu cầu từ ứng dụng đến cơ sở dữ liệu ASPState rất chậm. Tôi tin rằng điều này là do có các khóa độc quyền đang được giữ trên bàn bằng thủ tục DeleteExpiredSments

Mã số:

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                          
  • Tệp nhật ký được lấp đầy và trong một số trường hợp buộc tự động phát triển, mặc dù db đang trong quá trình khôi phục đơn giản

Ngoài ra, một dấu vết cho thấy nhiều yêu cầu cho cùng một phiên sắp diễn ra liên tiếp. Ví dụ: exec dbo.TempResetTimeout @id=N'32gghltsuoesnvlzbehchp2m2014c0f1'14 lần trong <1 giây, vì vậy chúng tôi tự hỏi về điều này là nguyên nhân hoặc tắc nghẽn, nhưng không chắc chắn về gốc rễ của hành vi này.

Bất kỳ đề xuất hoặc giải thích xung quanh hành vi này sẽ được đánh giá cao.


Bối cảnh của trạng thái phiên là ở đây: msdn.microsoft.com/en-us/l Library / aa478952.aspx
reticentKoala

Chúng tôi đã thực hiện đề xuất sau: aspalliance.com/articleViewer.aspx?aId=1184&pId=-1
reticentKoala

Ah, tôi hiểu rồi, đây là một sự thay thế. Bạn đã thay thế bản gốc bởi vì bạn đang gặp vấn đề sau đó, hoặc bởi vì một người nào đó trên Internet đã nói như vậy? Tôi sẽ đề nghị cố gắng chuyển trở lại ban đầu để xem liệu triệu chứng trở nên tốt hơn hay tồi tệ hơn. Để giảm khả năng chặn, bạn cũng có thể làmSELECT 1; WHILE @@ROWCOUNT <> 0 BEGIN DELETE TOP (10) ... END
Aaron Bertrand

Bởi vì quy trình kéo dài> 1 phút vào thời điểm bận rộn, có một mối nguy hiểm là 2 bản sao của Proc đang cố xóa cùng một hàng, việc đặt hàng bởi NEWID làm giảm khả năng này.
reticentKoala

2
Tôi đã viết một bài đăng trên blog về một số cải tiến tiềm năng để làm cho tác động của ASPState ít được chú ý hơn: sqlperformance.com/2013/01/t-sql-queries/optizes-aspstate
Aaron Bertrand

Câu trả lời:


5

Tôi nghi ngờ bạn đã thực hiện quy trình thay thế của Greg là tối ưu hóa trước. Cách tiếp cận một hàng một lần hạn chế khóa thành một hàng duy nhất, chắc chắn, nhưng sẽ mất nhiều thời gian hơn - đặc biệt nếu bạn buộc SQL Server tấn công các hàng theo thứ tự ngẫu nhiên.

Đề nghị của tôi sẽ trở lại quy trình ban đầu:

ALTER PROCEDURE dbo.DeleteExpiredSessions
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @now DATETIME;
  SET @now = GETUTCDATE();

  DELETE ASPState..ASPStateTempSessions 
    WHERE Expires < @now;
END
GO

Nếu bạn thấy rằng điều này trở thành một vấn đề về hiệu suất do các khóa được thực hiện, bạn có thể tách nó ra và thậm chí giảm tác động lên các bản ghi bằng cách sử dụng một cái gì đó như:

ALTER PROCEDURE dbo.DeleteExpiredSessions
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @now DATETIME, @c INT;
  SELECT @now = GETUTCDATE(), @c = 1;

  BEGIN TRANSACTION;

  WHILE @c <> 0
  BEGIN
    ;WITH x AS 
    (
      SELECT TOP (1000) SessionId
        FROM dbo.ASPStateTempSessions
        WHERE Expires < @now
        ORDER BY SessionId
    ) 
    DELETE x;

    SET @c = @@ROWCOUNT;

    IF @@TRANCOUNT = 1
    BEGIN
      COMMIT TRANSACTION;
      BEGIN TRANSACTION;
    END
  END

  IF @@TRANCOUNT = 1
  BEGIN
    COMMIT TRANSACTION;
  END
END
GO

Điều này sẽ tốt hơn nhiều, IMHO, hơn là sử dụng một con trỏ ngẫu nhiên để xóa từng hàng một lần. Bạn có thể điều chỉnh giá trị TOP (1000)dựa trên quan sát thực tế.

Một vài ý tưởng khác có thể giúp:

(a) đặt mô hình khôi phục của cơ sở dữ liệu ASPState thành đơn giản (mặc định là đầy đủ).

(b) thay đổi ASPState_Job_DeleteExpiredSessionsđể chạy cứ sau 5 hoặc 10 phút thay vì mỗi phút. Nếu công việc này mất> 1 phút để chạy thì nó sẽ luôn chạy. Hy vọng rằng nó không hoàn toàn tuyến tính, có nghĩa là chờ 5 phút thay vì 1 sẽ không xếp hàng hơn 5 phút làm việc thay vì 1. Thực hiện các đề xuất của tôi ở trên sẽ giúp ích cho việc này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.