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 (example@sqldat.com 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