はじめに
アプリケーションがデータベース接続を長期間維持する場合があります。それは重要ではないようです。ただし、このアプリケーションが多くの接続を確立する場合、またはそのような動作をするアプリケーションが複数ある場合は、状況はさらに悪化します。
この記事はチュートリアルではありません。この問題の可能な解決策について説明します。いつものように、私は代替の解決策を聞いてうれしいです。
ソリューション
1.指定されたデータベースへの特定のユーザーのすべての接続または接続を閉じるストアドプロシージャを作成します。
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 このストアドプロシージャは、データベースまたは特定のユーザーへのすべての接続を手動で無効にして、データベースでさらにアクションを実行するのに役立ちます。
2.ストアドプロシージャを作成して、スタックしたプロセスをすべて削除します。
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 このストアドプロシージャは、24時間以上前に完了した接続を削除します。さらに、この手順はメインシステムデータベース(master、tempdb、model、およびmsdb)には影響しません。接続が無効になっているときにデータベースにアクセスしようとすると、このアプリケーションの新しい接続が作成されます。
ここで、エージェントタスクでストアドプロシージャを1日1回実行する必要があります。
exec [DATABASE_NAME].[srv].[KillFullOldConnect];
このクエリをtry-catchブロックにラップして、例外の可能性のある呼び出しを処理することをお勧めします。
結果
この記事では、データベース(すべてまたは特定のユーザー)への接続を閉じるときにストアドプロシージャを実装する方法と、特定の例でスタックしたプロセスを削除する方法を分析しました。さらに、特定の例で、スタックしたプロセスの削除でタスクを毎日自動的に実行する方法を検討しました。これにより、サーバーへの「デッド」接続の量を減らすことができます。データベースへのすべての接続を削除すると、一部のプロパティを変更したり、問題の原因となったプロセスを閉じたりすることができます。
参照:
»sysprocesses
»kill
»db_id
»@@SPID