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