web-dev-qa-db-ja.com

ユーザー接続の最大数

SQL Server 2012 Standardエディションでは、ユーザー接続の最大数が32,767であることを知っています。この数に向かっている場合、DBAとして何をすべきですか?

現在、30,000のユーザー接続があり、この数は増加すると予想されます。

enter image description here

24
sebeid

接続の最大数 SQL Serverのバージョンとエディション全体で32,767です。

SQL Serverが現在持っている接続の数は、次の内容で確認できます。

SELECT ConnectionStatus = CASE WHEN dec.most_recent_sql_handle = 0x0 
        THEN 'Unused' 
        ELSE 'Used' 
        END
    , CASE WHEN des.status = 'Sleeping' 
        THEN 'sleeping' 
        ELSE 'Not Sleeping' 
        END
    , ConnectionCount = COUNT(1)
FROM sys.dm_exec_connections dec
    INNER JOIN sys.dm_exec_sessions des ON dec.session_id = des.session_id
GROUP BY CASE WHEN des.status = 'Sleeping' 
        THEN 'sleeping' 
        ELSE 'Not Sleeping' 
        END
    , CASE WHEN dec.most_recent_sql_handle = 0x0 
        THEN 'Unused' 
        ELSE 'Used' 
        END;

上記のクエリからの使用済み接続と未使用接続の比率が関係している場合は、サーバーに接続されているクライアントアプリケーションによって接続プールが有効になっており、それらの接続が効率的に使用されていない可能性があります。開発者にこれらのアプリケーションの接続文字列を変更して接続プールのサイズを制限させ、接続が適切に破棄されていることを確認することをお勧めします。接続が正しく破棄されていない場合、クライアントアプリケーションが実行されている限り、接続は開いたままになります。

特に狂ったように感じていて、最近何も実行していないすべての接続を取り除く必要がある場合(実際に実行しているかどうかに関係なく実行している場合)作業)、次のコードを実行すると、強制終了できるセッションのリストが生成されます。コマンドを実際に実行するには、生成されたコマンドをコピーして新しいSSMSウィンドウに貼り付ける必要があります。また、念のため、履歴書を最新に更新することもお勧めします

DECLARE @cmd NVARCHAR(MAX);
SET @cmd = '';
SELECT @cmd = @cmd + 
    CASE WHEN @cmd = '' THEN '' ELSE CHAR(13) + CHAR(10) END 
    + 'KILL ' + CONVERT(VARCHAR(MAX), dec.session_id) + ';'
FROM sys.dm_exec_connections dec
WHERE dec.most_recent_sql_handle = 0x0;

PRINT @cmd;

複数のSQL Serverノード間でデータをシャーディングすることにより、接続数を32,767を超えて線形にスケーリングすることが可能です。ただし、私の意見では、接続数の制限を回避する方法としてシャーディングを使用することは、atom爆弾を使用してクモを殺すことと似ています。それはwillスパイダーを殺しますが、1日の終わりにmightより大きな問題が発生する可能性があります。 atom爆弾を構築するのは非常に難しいことです。適切にシャーディングを実装することは言うまでもありません。

31
Max Vernon

私は過去に接続プーリングで奇妙な動作に遭遇しましたが、あなたのシナリオはそれらの状況の1つとうまく一致しています。アプリケーションが接続プーリングを使用している場合(そして、現時点では、それを確認または拒否するまではまだ推測です)、開いたままの接続が多数あります。これは仕様によるものです。

接続プールは、データベース接続を作成するオーバーヘッドを削減することを目的としています。たとえば、接続プールが3であるとします。私が知る限り、ライフサイクルは次のようになります(コールド接続プールキャッシュから開始)。

  1. アプリケーションユーザーAがデータベースへの接続を要求する
  2. 接続プールはデータベースへの接続スレッド1を開始します
  3. アプリケーションユーザーBがデータベースへの接続を要求する
  4. 接続プールはデータベースへの接続スレッド2を開始します
  5. アプリケーションユーザーAが接続を閉じます... 接続プールへ
  6. アプリケーションユーザーCがデータベースへの接続を要求する
  7. 接続プールの問題sp_reset_connectionスレッド1
  8. 接続プールはアプリケーションユーザーCにスレッド1を割り当てます

これは単純化しすぎですが、重要な点は次のとおりです。

  • データベースまたは接続プールが接続を強制的に閉じるまで、接続は接続プールスレッドプールとデータベースの間で開いたままになります。
  • 接続は、そのスレッドが別のユーザーによって再利用されるまで、最後のセッション実行コンテキストで開いたままになり、その時点でsp_reset_connectionが呼び出されます。

これらの結論に至るまでに使用した参考資料を以下に示します。

SQL Server DBAの接続プーリング

孤立したトランザクションの場合

12
swasheck