Introdução
Há situações em que os aplicativos mantêm a conexão com o banco de dados por um longo período de tempo. Parece não ser importante. No entanto, se esse aplicativo fizer muitas conexões ou houver vários aplicativos com esse comportamento — as coisas estão piorando.
Este artigo não é um tutorial. Descreve possíveis soluções para este problema. Como de costume, ficarei feliz em ouvir quaisquer soluções alternativas.
Solução
1. Crie um procedimento armazenado que feche todas as conexões ou conexões de um determinado usuário com o banco de dados especificado:
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
Esse procedimento armazenado ajuda a desabilitar manualmente todas as conexões com o banco de dados ou um determinado usuário para ações adicionais com o banco de dados.
2. Crie um procedimento armazenado para remover todos os processos travados.
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
Este procedimento armazenado remove as conexões que foram concluídas há mais de 24 horas. Além disso, esse procedimento não afeta os principais bancos de dados do sistema (master, tempdb, model e msdb). Se você tentar acessar um banco de dados enquanto a conexão estiver desabilitada, uma nova conexão para este aplicativo será criada.
Agora, é necessário executar um procedimento armazenado na tarefa Agente uma vez por dia:
exec [DATABASE_NAME].[srv].[KillFullOldConnect];
Seria melhor envolver essa consulta no bloco try-catch para processar uma possível chamada para exceções.
Resultado
Neste artigo, analisei como implementar procedimentos armazenados ao fechar uma conexão com um banco de dados (todos ou um determinado usuário) e excluir processos travados em um exemplo específico. Além disso, explorei em um exemplo específico como executar diariamente uma tarefa na exclusão de processos travados. Permite diminuir uma quantidade de conexões ‘mortas’ para um servidor. A exclusão de todas as conexões com o banco de dados permite modificar algumas propriedades, bem como fechar o processo que causa algum problema.
Referências:
» sysprocesses
» matar
» db_id
» @@SPID