Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Suppression automatique des processus bloqués dans MS SQL Server

Présentation

Dans certaines situations, les applications conservent la connexion à la base de données pendant une longue période. Il semble que ce ne soit pas important. Cependant, si cette application établit de nombreuses connexions ou s'il existe plusieurs applications avec un tel comportement, les choses empirent.

Cet article n'est pas un tutoriel. Il décrit les solutions possibles à ce problème. Comme d'habitude, je serai heureux d'entendre toute solution alternative.

Solution

1. Créez une procédure stockée qui ferme toutes les connexions ou les connexions d'un certain utilisateur à la base de données spécifiée :

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

Cette procédure stockée permet de désactiver manuellement toutes les connexions à la base de données ou à un certain utilisateur pour d'autres actions avec la base de données.

2. Créez une procédure stockée pour supprimer tous les processus bloqués.

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

Cette procédure stockée supprime les connexions établies il y a plus de 24 heures. De plus, cette procédure n'affecte pas les principales bases de données système (master, tempdb, model et msdb). Si vous essayez d'accéder à une base de données alors que la connexion est désactivée, une nouvelle connexion pour cette application sera créée.

Désormais, il est nécessaire d'exécuter une procédure stockée dans la tâche Agent une fois par jour :

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

Il serait préférable d'encapsuler cette requête dans le bloc try-catch pour traiter un éventuel appel d'exceptions.

Résultat

Dans cet article, j'ai analysé comment implémenter des procédures stockées sur la fermeture d'une connexion à une base de données (tous ou un certain utilisateur) et supprimer les processus bloqués sur un exemple particulier. De plus, j'ai exploré sur un exemple particulier comment exécuter automatiquement une tâche sur la suppression des processus bloqués au quotidien. Il permet de diminuer le nombre de connexions "mortes" à un serveur. La suppression de toutes les connexions à la base de données vous permet de modifier certaines propriétés, ainsi que de fermer le processus qui pose problème.

Références :

» sysprocesses
» kill
» db_id
» @@SPID