Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Automatisches Löschen festgefahrener Prozesse in MS SQL Server

Einführung

Es gibt Situationen, in denen Anwendungen die Datenbankverbindung über einen längeren Zeitraum aufrechterhalten. Es scheint nicht wichtig zu sein. Wenn diese Anwendung jedoch viele Verbindungen herstellt oder es mehrere Anwendungen mit einem solchen Verhalten gibt, wird die Sache noch schlimmer.

Dieser Artikel ist kein Tutorial. Es beschreibt mögliche Lösungen für dieses Problem. Wie üblich freue ich mich über alternative Lösungen.

Lösung

1. Erstellen Sie eine gespeicherte Prozedur, die alle Verbindungen oder Verbindungen eines bestimmten Benutzers mit der angegebenen Datenbank schließt:

USE [DATABASE_NAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [srv].[KillConnect]
    @databasename nvarchar(255), -- database
    @loginname    nvarchar(255)=NULL  -- login details
AS
BEGIN
    /*
     deletes connections for the specified database and login details access
    */
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    if(@databasename is null)
    begin
        ;THROW 50000, 'A database is not specified!', 0;
    end
    else
    begin
        declare @dbid int=db_id(@databasename);

        if(@dbid is NULL)
        begin
            ;THROW 50000, 'The database does not exist!', 0;
        end
        else if @dbid <= 4
        begin
            ;THROW 50000, 'To delete connections to a system database is forbidden!', 0;
        end
        else
        begin
            declare @query nvarchar(max);
            set @query = '';

            select @query=coalesce(@query,',' )
                        +'kill '
                        +convert(varchar, spid)
                        +'; '
            from master..sysprocesses
            where dbid=db_id(@databasename)
            and spid<>@@SPID
            and ([email protected] or @loginname is null);

            if len(@query) > 0
            begin
                begin try
                    exec(@query);
                end try
                begin catch
                end catch
            end
        end
    end
END

GO

Diese gespeicherte Prozedur hilft bei der manuellen Deaktivierung aller Verbindungen zur Datenbank oder eines bestimmten Benutzers für weitere Aktionen mit der Datenbank.

2. Erstellen Sie eine gespeicherte Prozedur, um alle hängengebliebenen Prozesse zu entfernen.

USE [DATABASE_NAME]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [srv].[KillFullOldConnect]
AS
BEGIN
    /*
       It deletes the connections which were executed a day ago. 
       Attention! System databases such as master, tempdb, model and msdb 
       do not take part in this process. 
       However, it does not affect database distribution for replication.
    */
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

    declare @query nvarchar(max);
    set @query = '';

    select @query=coalesce(@query,',' )
                +'kill '
                +convert(varchar, spid)
                +'; '
    from master..sysprocesses
    where dbid>4
    and [last_batch]<dateadd(day,-1,getdate())
    order by [last_batch]

    if len(@query) > 0
    begin
        begin try
            exec(@query);
        end try
        begin catch
        end catch
    end
END
GO

Diese gespeicherte Prozedur entfernt die Verbindungen, die vor mehr als 24 Stunden hergestellt wurden. Darüber hinaus wirkt sich dieses Verfahren nicht auf die Hauptsystemdatenbanken (master, tempdb, model und msdb) aus. Wenn Sie versuchen, auf eine Datenbank zuzugreifen, während die Verbindung deaktiviert ist, wird eine neue Verbindung für diese Anwendung erstellt.

Jetzt ist es notwendig, einmal täglich eine gespeicherte Prozedur in der Agentenaufgabe auszuführen:

exec [DATABASE_NAME].[srv].[KillFullOldConnect];

Es wäre besser, diese Abfrage in den Try-Catch-Block zu packen, um einen möglichen Aufruf für Ausnahmen zu verarbeiten.

Ergebnis

In diesem Artikel habe ich analysiert, wie gespeicherte Prozeduren zum Schließen einer Verbindung zu einer Datenbank (alle oder ein bestimmter Benutzer) implementiert und an einem bestimmten Beispiel festgefahrene Prozesse gelöscht werden. Darüber hinaus habe ich an einem bestimmten Beispiel untersucht, wie Sie täglich automatisch eine Aufgabe zum Löschen festgefahrener Prozesse ausführen können. Es ermöglicht die Verringerung der Anzahl „toter“ Verbindungen zu einem Server. Durch das Löschen aller Verbindungen zur Datenbank können Sie einige Eigenschaften ändern und den Prozess schließen, der Probleme verursacht.

Referenzen:

» sysprocesses
» kill
» db_id
» @@SPID