Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Exclusão automática de processos presos no MS SQL Server

Introdução


Há situações em que os aplicativos mantêm a conexão com o banco de dados por um longo período de tempo. Parece não ser importante. No entanto, se esse aplicativo fizer muitas conexões ou houver vários aplicativos com esse comportamento — as coisas estão piorando.

Este artigo não é um tutorial. Descreve possíveis soluções para este problema. Como de costume, ficarei feliz em ouvir quaisquer soluções alternativas.


Solução


1. Crie um procedimento armazenado que feche todas as conexões ou conexões de um determinado usuário com o banco de dados especificado:
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

Esse procedimento armazenado ajuda a desabilitar manualmente todas as conexões com o banco de dados ou um determinado usuário para ações adicionais com o banco de dados.

2. Crie um procedimento armazenado para remover todos os processos travados.
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

Este procedimento armazenado remove as conexões que foram concluídas há mais de 24 horas. Além disso, esse procedimento não afeta os principais bancos de dados do sistema (master, tempdb, model e msdb). Se você tentar acessar um banco de dados enquanto a conexão estiver desabilitada, uma nova conexão para este aplicativo será criada.

Agora, é necessário executar um procedimento armazenado na tarefa Agente uma vez por dia:
exec [DATABASE_NAME].[srv].[KillFullOldConnect];

Seria melhor envolver essa consulta no bloco try-catch para processar uma possível chamada para exceções.

Resultado


Neste artigo, analisei como implementar procedimentos armazenados ao fechar uma conexão com um banco de dados (todos ou um determinado usuário) e excluir processos travados em um exemplo específico. Além disso, explorei em um exemplo específico como executar diariamente uma tarefa na exclusão de processos travados. Permite diminuir uma quantidade de conexões ‘mortas’ para um servidor. A exclusão de todas as conexões com o banco de dados permite modificar algumas propriedades, bem como fechar o processo que causa algum problema.

Referências:


» sysprocesses
» matar
» db_id
» @@SPID