sql >> データベース >  >> RDS >> Sqlserver

MSSQLServerでスタックしたプロセスの自動削除

    はじめに

    アプリケーションがデータベース接続を長期間維持する場合があります。それは重要ではないようです。ただし、このアプリケーションが多くの接続を確立する場合、またはそのような動作をするアプリケーションが複数ある場合は、状況はさらに悪化します。

    この記事はチュートリアルではありません。この問題の可能な解決策について説明します。いつものように、私は代替の解決策を聞いてうれしいです。

    ソリューション

    1.指定されたデータベースへの特定のユーザーのすべての接続または接続を閉じるストアドプロシージャを作成します。

    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

    このストアドプロシージャは、データベースまたは特定のユーザーへのすべての接続を手動で無効にして、データベースでさらにアクションを実行するのに役立ちます。

    2.ストアドプロシージャを作成して、スタックしたプロセスをすべて削除します。

    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

    このストアドプロシージャは、24時間以上前に完了した接続を削除します。さらに、この手順はメインシステムデータベース(master、tempdb、model、およびmsdb)には影響しません。接続が無効になっているときにデータベースにアクセスしようとすると、このアプリケーションの新しい接続が作成されます。

    ここで、エージェントタスクでストアドプロシージャを1日1回実行する必要があります。

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

    このクエリをtry-catchブロックにラップして、例外の可能性のある呼び出しを処理することをお勧めします。

    結果

    この記事では、データベース(すべてまたは特定のユーザー)への接続を閉じるときにストアドプロシージャを実装する方法と、特定の例でスタックしたプロセスを削除する方法を分析しました。さらに、特定の例で、スタックしたプロセスの削除でタスクを毎日自動的に実行する方法を検討しました。これにより、サーバーへの「デッド」接続の量を減らすことができます。データベースへのすべての接続を削除すると、一部のプロパティを変更したり、問題の原因となったプロセスを閉じたりすることができます。

    参照:

    »sysprocesses
    »kill
    »db_id
    »@@SPID


    1. MySQLTunerを使用してMySQLのパフォーマンスを最適化する方法

    2. MySQL:データベースに対する**すべての**権限を付与します

    3. MySQL –最小および最大の比較演算子

    4. Elasticsearchを使用したMicrosoftAccessデータの検索