Inleiding
Er zijn situaties waarin toepassingen de databaseverbinding voor een lange periode behouden. Het schijnt niet belangrijk te zijn. Als deze applicatie echter veel verbindingen maakt of als er meerdere applicaties zijn met dergelijk gedrag, wordt het erger.
Dit artikel is geen zelfstudie. Het beschrijft mogelijke oplossingen voor dit probleem. Zoals gewoonlijk hoor ik graag alternatieve oplossingen.
Oplossing
1. Maak een opgeslagen procedure die alle verbindingen of verbindingen van een bepaalde gebruiker met de opgegeven database sluit:
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 Deze opgeslagen procedure helpt bij het handmatig uitschakelen van alle verbindingen met de database of een bepaalde gebruiker voor verdere acties met de database.
2. Maak een opgeslagen procedure om alle vastgelopen processen te verwijderen.
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 Deze opgeslagen procedure verwijdert de verbindingen die meer dan 24 uur geleden zijn voltooid. Bovendien heeft deze procedure geen invloed op de belangrijkste systeemdatabases (master, tempdb, model en msdb). Als u probeert toegang te krijgen tot een database terwijl de verbinding is uitgeschakeld, wordt er een nieuwe verbinding voor deze toepassing gemaakt.
Nu is het nodig om één keer per dag een opgeslagen procedure in de Agent-taak uit te voeren:
exec [DATABASE_NAME].[srv].[KillFullOldConnect];
Het zou beter zijn om deze vraag in het try-catch-blok te plaatsen om een mogelijke oproep voor uitzonderingen te verwerken.
Resultaat
In dit artikel heb ik geanalyseerd hoe opgeslagen procedures kunnen worden geïmplementeerd bij het sluiten van een verbinding met een database (alle of een bepaalde gebruiker) en hoe vastgelopen processen op een bepaald voorbeeld kunnen worden verwijderd. Daarnaast heb ik in een bepaald voorbeeld onderzocht hoe ik dagelijks automatisch een taak op het verwijderen van vastgelopen processen kan uitvoeren. Het maakt het mogelijk om het aantal 'dode' verbindingen met een server te verminderen. Door alle verbindingen met de database te verwijderen, kunt u enkele eigenschappen wijzigen en het proces sluiten dat een probleem veroorzaakt.
Referenties:
» sysprocesses
» kill
» db_id
» @@SPID