sql >> Databasteknik >  >> RDS >> Sqlserver

Automatisk radering av processer som har fastnat i MS SQL Server

Introduktion

Det finns situationer när applikationer behåller databasanslutningen under en lång tid. Det verkar inte vara viktigt. Men om den här applikationen gör många kopplingar eller om det finns flera applikationer med sådant beteende — saker och ting blir värre.

Den här artikeln är inte en handledning. Den beskriver möjliga lösningar på detta problem. Som vanligt kommer jag gärna höra eventuella alternativa lösningar.

Lösning

1. Skapa en lagrad procedur som stänger alla anslutningar eller anslutningar för en viss användare till den angivna databasen:

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

Denna lagrade procedur hjälper till att manuellt inaktivera alla anslutningar till databasen eller en viss användare för ytterligare åtgärder med databasen.

2. Skapa en lagrad procedur för att ta bort alla processer som har fastnat.

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

Denna lagrade procedur tar bort anslutningar som slutfördes för mer än 24 timmar sedan. Dessutom påverkar denna procedur inte huvudsystemets databaser (master, tempdb, model och msdb). Om du försöker komma åt en databas medan anslutningen är inaktiverad skapas en ny anslutning för denna applikation.

Nu är det nödvändigt att köra en lagrad procedur i agentuppgiften en gång om dagen:

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

Det skulle vara bättre att lägga in den här frågan i try-catch-blocket för att bearbeta ett eventuellt anrop för undantag.

Resultat

I den här artikeln har jag analyserat hur man implementerar lagrade procedurer för att stänga en anslutning till en databas (alla eller en viss användare) och för att ta bort processer som har fastnat på ett visst exempel. Dessutom har jag undersökt ett särskilt exempel hur man automatiskt kör en uppgift på de processer som har fastnat för borttagning på daglig basis. Det tillåter att minska mängden "döda" anslutningar till en server. Raderingen av alla anslutningar till databasen låter dig ändra vissa egenskaper, samt stänga processen som orsakar problem.

Referenser:

» sysprocesser
» döda
» db_id
» @@SPID


  1. Rätt verktyg gör att trimningen fungerar snabbt

  2. Vad är det bästa sättet att testa SQL Server-anslutning programmatiskt?

  3. Hur man ändrar datatyp i Oracle med befintliga rader i tabellen

  4. Skriv in dessa tabellvärdade parametrar