SQL Serverのパフォーマンスを見ていて、接続数が多くなるとCPU使用率が高くなることに気づきました(これは正常であると思います)。通常、平均接続数は約120でしたが、過去1週間からの接続数は平均は200以上になり、時には400以上になることもあります。これにより、CPU使用率が高くなり、続いてメモリプレッシャーが発生し始め、プランキャッシュがフラッシュされます(長期的な解決策としてLPIMをオンにする必要がある場合があります)。
これはパフォーマンスの問題を引き起こしています。だから私はデータベースの開いているセッションをチェックし、以下は結果です:
これらの70の接続/セッションは、ネットワーク経由でアプリケーションにアクセスする実際のユーザーからのものです。 SSRSからの接続はほとんどなく、最後の4セットの接続は、開発者/ DBAからのリモートデスクトップ接続です。
これらの120の接続が何であるかはわかりません。これらの接続にはLoginNameさえありません。
Sys.dm_exec_sessionから詳細をキャプチャしました。どうやら、ログイン名のないセッションは何もしません。 0 CPU時間、0論理読み取りなどを使用します。
他にどこを見ればいいのかわかりません。
Sidのsys.sysloginsからの結果。ログインは、実際のユーザーからのログインと同じです。
70の接続は、.Netアプリケーションの汎用SQLログインを使用しています。ログイン名のない他の120の接続は同じSIDを持っています。
ユーザーがアプリケーションにログインして別のモジュールに切り替えた後、同じモジュールに戻って重複セッションが作成され、実際のセッションが開いたままになっている場合に発生しますか?
これはの結果です
SELECT con.*, '--' AS [---], ses.*, '--' AS [---], req.*
FROM sys.dm_exec_connections con
INNER JOIN sys.dm_exec_sessions ses ON con.[session_id] = ses.[session_id]
LEFT JOIN sys.dm_exec_requests req ON req.[session_id] = con.[session_id] WHERE ses.[login_name] = N''
最後に、ログイン名のないそれらのセッションが何をしているかを見つけました。彼らは、メインのクエリ/ストアドプロシージャから呼び出される関数を実行しています。
これが私が使ったクエリです。
SELECT
con.connection_id,ses.status,ses.Host_name,ses.Host_process_id,ses.program_name,ses.last_request_start_time,ses.last_request_end_time,req.status,req.command,
Substring(st.TEXT,(req.statement_start_offset / 2) + 1, ((CASE req.statement_end_offset WHEN -1 THEN Datalength(st.TEXT) ELSE req.statement_end_offset END - req.statement_start_offset) / 2) + 1) AS statement_text
FROM sys.dm_exec_connections con
INNER JOIN sys.dm_exec_sessions ses ON con.[session_id] = ses.[session_id]
LEFT JOIN sys.dm_exec_requests req ON req.[session_id] = con.[session_id]
CROSS APPLY sys.Dm_exec_sql_text(req.sql_handle) AS st
WHERE ses.[login_name] = N''
これらのセッションは関数のみを実行します。なぜこれが起こっているのかわかりません。これは正常な動作ですか?
次のような関連テーブルをクエリしたい場合があります。
...何も起こらなくても、何が起こっているかの概要を知ること。
このようなものを実行して、システムで何が起こっているか、どのリソースが使用されているかを確認します。
SELECT des1.session_id AS Session_ID_S,
--des1.context_info as Session_Contxt_Info,
--dec1.session_id AS Session_ID_C,
dowt.session_id AS Session_ID_WT,
dowt.exec_context_id AS Exec_Contxt_ID,
sdb.name AS DatabaseName,
ssp.name AS SQL_Login_Name,
des1.nt_user_name AS NT_User_Name,
--'--kill ' + cast(dec1.session_id as nvarchar(20)) as killcommand,
dowt.wait_duration_ms AS Wait_Duration_ms,
dowt.wait_type AS Wait_Type,
dowt.blocking_session_id AS Blocking_Session_ID,
dowt.resource_description AS Ressource_Description,
des1.program_name AS Program_Name,
dest.[text] AS SQL_Text,
deqp.query_plan AS Query_Plan,
des1.cpu_time AS CPU_Time,
des1.memory_usage AS RAM_Usage
FROM sys.dm_exec_sessions AS des1
LEFT
JOIN sys.dm_exec_connections AS dec1
ON des1.session_id = dec1.session_id
LEFT -- comment out LEFT to display only sessions that have gone parallel
JOIN sys.dm_os_waiting_tasks AS dowt
ON des1.session_id = dowt.session_id
LEFT -- comment out LEFT to display only sessions currently executing statements
JOIN sys.dm_exec_requests AS der
ON des1.session_id = der.session_id
LEFT
JOIN sys.server_principals AS ssp
ON des1.login_name = ssp.name
LEFT
JOIN sys.databases as sdb
ON des1.database_id = sdb.database_id
OUTER APPLY sys.dm_exec_sql_text(der.sql_handle) AS dest -- Retrieve Actual SQL Text
OUTER APPLY sys.dm_exec_query_plan(der.plan_handle) AS deqp -- Retrieve Query Plan (XML)
WHERE des1.is_user_process = 1
ORDER BY
des1.session_id, dowt.exec_context_id
実行中のすべてのタスクの概要と、並列プロセス(CXCONSUMER/CXPACKET)がある場合に「root」セッションが作成されたアカウントを示します。出力の例は、次のスクリーンショットのようになります。
出力は、コメント化したLEFT
コマンドの数によって異なります。それらをすべてそのままにしておくと、すべてのセッションの完全なリストが表示されます(システムセッションなしsession_id < 50
)と問題を特定できるはずです。
ユーザーがアプリケーションにログインして別のモジュールに切り替えた後、同じモジュールに戻って重複セッションが作成され、実際のセッションが開いたままになっている場合に発生しますか?
それは答えられないことです。アプリケーションがどのように設計されているか、またモジュールスイッチが新しい接続を開始するかどうかはわかりません。
アプリケーションのバックグラウンドでなんらかの形のスレッドが発生している場合は、データベースの各接続のスレッドを監視しているだけかもしれません(例の出力。 [〜#〜]または[〜#〜]クエリオプティマイザがクエリを決定したため、クエリが並行して実行されていることがわかります並列処理が(部分的に)最適です。
次の例のように、ログイン名のないセッションが引き続き表示される場合:
...少なくとも、どのアプリケーション/プログラム/ステートメント/ 待機タイプ が問題の原因であるかを確認できます。この情報を利用して、さらに掘り下げることができます。