はじめに
アプリケーションがデータベース接続を長期間維持する場合があります。それは重要ではないようです。ただし、このアプリケーションが多くの接続を確立する場合、またはそのような動作をするアプリケーションが複数ある場合は、状況はさらに悪化します。
この記事はチュートリアルではありません。この問題の可能な解決策について説明します。いつものように、私は代替の解決策を聞いてうれしいです。
ソリューション
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 ([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
このストアドプロシージャは、データベースまたは特定のユーザーへのすべての接続を手動で無効にして、データベースでさらにアクションを実行するのに役立ちます。
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