Wprowadzenie
Zdarzają się sytuacje, w których aplikacje utrzymują połączenie z bazą danych przez długi czas. Wydaje się, że to nie jest ważne. Jeśli jednak ta aplikacja nawiązuje wiele połączeń lub istnieje kilka aplikacji zachowujących się w taki sposób — sytuacja się pogarsza.
Ten artykuł nie jest samouczkiem. Opisuje możliwe rozwiązania tego problemu. Jak zwykle z przyjemnością wysłucham wszelkich alternatywnych rozwiązań.
Rozwiązanie
1. Utwórz procedurę składowaną, która zamyka wszystkie połączenia lub połączenia określonego użytkownika z określoną bazą danych:
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 Ta procedura składowana pomaga ręcznie wyłączyć wszystkie połączenia z bazą danych lub określonego użytkownika w celu wykonania dalszych działań z bazą danych.
2. Utwórz procedurę składowaną, aby usunąć wszystkie zablokowane procesy.
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 Ta procedura składowana usuwa połączenia, które zostały zakończone ponad 24 godziny temu. Ponadto ta procedura nie wpływa na główne bazy danych systemu (master, tempdb, model i msdb). Jeśli spróbujesz uzyskać dostęp do bazy danych, gdy połączenie jest wyłączone, zostanie utworzone nowe połączenie dla tej aplikacji.
Teraz konieczne jest uruchomienie procedury składowanej w zadaniu Agenta raz dziennie:
exec [DATABASE_NAME].[srv].[KillFullOldConnect];
Lepiej byłoby umieścić to zapytanie w bloku try-catch, aby przetworzyć możliwe wywołanie wyjątków.
Wynik
W tym artykule przeanalizowałem, jak zaimplementować procedury składowane przy zamykaniu połączenia z bazą danych (wszystkim lub określonym użytkownikiem) i usuwać zablokowane procesy na konkretnym przykładzie. Ponadto zbadałem na konkretnym przykładzie, jak codziennie automatycznie uruchamiać zadanie po usunięciu zablokowanych procesów. Pozwala zmniejszyć liczbę „martwych” połączeń z serwerem. Usunięcie wszystkich połączeń z bazą danych umożliwia modyfikację niektórych właściwości, a także zamknięcie procesu, który powoduje jakikolwiek problem.
Referencje:
» procesy systemowe
» zabij
» db_id
» @@SPID