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 (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 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