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