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