Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Eliminazione automatica dei processi bloccati in MS SQL Server

Introduzione

Ci sono situazioni in cui le applicazioni mantengono la connessione al database per un lungo periodo di tempo. Sembra non essere importante. Tuttavia, se questa applicazione effettua molte connessioni o ci sono diverse applicazioni con tale comportamento, le cose stanno peggiorando.

Questo articolo non è un tutorial. Descrive le possibili soluzioni a questo problema. Come al solito, sarò lieto di ascoltare eventuali soluzioni alternative.

Soluzione

1. Creare una procedura memorizzata che chiude tutte le connessioni o connessioni di un determinato utente al database specificato:

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

Questa procedura memorizzata aiuta a disabilitare manualmente tutte le connessioni al database o un determinato utente per ulteriori azioni con il database.

2. Crea una procedura memorizzata per rimuovere tutti i processi bloccati.

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

Questa procedura memorizzata rimuove le connessioni che sono state completate più di 24 ore fa. Inoltre, questa procedura non influisce sui database di sistema principali (master, tempdb, model e msdb). Se tenti di accedere a un database mentre la connessione è disabilitata, verrà creata una nuova connessione per questa applicazione.

Ora è necessario eseguire una stored procedure nell'attività Agent una volta al giorno:

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

Sarebbe meglio racchiudere questa query nel blocco try-catch per elaborare una possibile richiesta di eccezioni.

Risultato

In questo articolo, ho analizzato come implementare le stored procedure sulla chiusura di una connessione a un database (tutti o un determinato utente) e come eliminare i processi bloccati su un particolare esempio. Inoltre, ho esplorato su un esempio particolare come eseguire automaticamente un'attività sull'eliminazione dei processi bloccati su base giornaliera. Consente di ridurre una quantità di connessioni "morte" a un server. L'eliminazione di tutte le connessioni al database consente di modificare alcune proprietà, oltre a chiudere il processo che causa qualsiasi problema.

Riferimenti:

» sysprocesses
» kill
» db_id
» @@SPID