Oracleを運用していると、こんな場面が必ずきます。
- 誰かのSQL処理がハングしてDBが重くなっている
- 不要なセッションが大量に接続されている
- ロックが解放されず後続処理が詰まっている
そんなときに使うのが V$SESSION ビューと ALTER SYSTEM KILL SESSION コマンドです。
この記事では、現場SE歴20年超の筆者がOracleのセッション一覧を確認するSQLとセッションを強制切断する手順を、実際の運用で使えるレベルで解説します。
V$SESSIONとは
V$SESSION はOracleの動的パフォーマンスビューで、現在DBに接続しているすべてのセッション情報が格納されています。
参照には DBA権限(system / sys)、または SELECT ANY DICTIONARY 権限が必要です。
基本:接続中のセッション一覧を確認する
sql
SELECT
SID
,SERIAL#
,USERNAME AS ユーザー名
,STATUS AS 状態
,MACHINE AS 接続元マシン名
,PROGRAM AS 接続プログラム
,MODULE AS モジュール名
,LOGON_TIME AS ログイン日時
,LAST_CALL_ET AS 最終操作からの経過秒
FROM V$SESSION
WHERE USERNAME IS NOT NULL -- バックグラウンドプロセスを除外
ORDER BY LOGON_TIME ASC
;STATUSの意味
| STATUS値 | 意味 |
|---|---|
| ACTIVE | 現在SQLを実行中 |
| INACTIVE | 接続中だがSQL未実行(アイドル) |
| KILLED | KILL SESSION実行済み(まだ完全終了していない) |
| CACHED | セッションキャッシュ中 |
応用:ユーザー別のセッション数を集計する
接続数が多い原因を調べるときに使います。
sql
SELECT
USERNAME AS ユーザー名
,STATUS AS 状態
,COUNT(*) AS セッション数
FROM V$SESSION
WHERE USERNAME IS NOT NULL
GROUP BY USERNAME, STATUS
ORDER BY セッション数 DESC
;応用:長時間実行中のセッションを抽出する
LAST_CALL_ET(最終操作からの経過秒)が大きいセッションを探します。
sql
SELECT
SID
,SERIAL#
,USERNAME
,STATUS
,LAST_CALL_ET AS 経過秒
,SQL_ID
,MACHINE
,PROGRAM
FROM V$SESSION
WHERE USERNAME IS NOT NULL
AND STATUS = 'ACTIVE'
AND LAST_CALL_ET > 300 -- 5分以上実行中のものを抽出
ORDER BY LAST_CALL_ET DESC
;応用:実行中のSQLも一緒に確認する
どんなSQLを実行しているかを V$SQL と結合して確認できます。
sql
SELECT
S.SID
,S.SERIAL#
,S.USERNAME
,S.STATUS
,S.LAST_CALL_ET AS 経過秒
,S.MACHINE
,S.PROGRAM
,Q.SQL_TEXT AS 実行中SQL
FROM V$SESSION S
LEFT JOIN V$SQL Q ON S.SQL_ID = Q.SQL_ID
WHERE S.USERNAME IS NOT NULL
AND S.STATUS = 'ACTIVE'
ORDER BY S.LAST_CALL_ET DESC
;セッションを強制切断する(KILL SESSION)
特定のセッションを強制終了するには ALTER SYSTEM KILL SESSION を使います。
手順1:切断対象のSIDとSERIAL#を確認
sql
SELECT SID, SERIAL#, USERNAME, STATUS, MACHINE, PROGRAM
FROM V$SESSION
WHERE USERNAME = '切断したいユーザー名'
;手順2:KILL SESSIONを実行
sql
ALTER SYSTEM KILL SESSION 'SID, SERIAL#' IMMEDIATE;
-- 実行例(SID=45、SERIAL#=1234の場合):
ALTER SYSTEM KILL SESSION '45, 1234' IMMEDIATE;
IMMEDIATEをつける理由: つけないと、Oracleがセッションに自発的に終了するよう要求するだけで、実際の終了まで数分かかることがあります。緊急時は必ずIMMEDIATEを指定してください。
複数セッションをまとめて切断する
特定ユーザーの全セッションをまとめて切断したい場合は、以下のPL/SQLブロックが便利です。
sql
BEGIN
FOR s IN (
SELECT SID, SERIAL#
FROM V$SESSION
WHERE USERNAME = '切断したいユーザー名'
AND STATUS = 'INACTIVE' -- アイドルセッションのみを対象
) LOOP
EXECUTE IMMEDIATE
'ALTER SYSTEM KILL SESSION ''' || s.SID || ',' || s.SERIAL# || ''' IMMEDIATE';
END LOOP;
END;
/⚠️
ACTIVEセッションを強制切断すると、実行中のトランザクションがロールバックされます。業務への影響を必ず確認してから実行してください。
KILL後もセッションが消えない場合
STATUS = 'KILLED' のセッションが残り続けることがあります。これはOracleがロールバック処理中の場合です。
sql
-- KILLED状態のセッションを確認
SELECT SID, SERIAL#, STATUS, USERNAME, LAST_CALL_ET
FROM V$SESSION
WHERE STATUS = 'KILLED'
;通常はロールバックが完了すると自動的に消えます。長時間(30分以上)消えない場合は、OSプロセスを強制終了することも検討します(DBA判断で実施)。
よくある質問(FAQ)
Q. 自分自身のセッションを切断できますか?
自分自身のセッションはKILLできません。別の管理者アカウントで実行する必要があります。
Q. V$SESSIONを見るにはどんな権限が必要ですか?
SELECT ANY DICTIONARY 権限、または DBA ロールが必要です。一般ユーザーはデフォルトでは参照できません。
Q. セッションを切断するとデータが消えますか?
KILL SESSIONを実行すると、そのセッションの未コミットトランザクションは自動的にロールバックされます。コミット済みのデータには影響しません。
Q. セッション一覧に同じSIDが複数出ます。なぜですか?
USERNAME IS NOT NULL の条件で絞ればバックグラウンドプロセスは除外できます。それでも重複する場合、接続プーリングなどで同一ユーザーが複数セッションを持っています。
まとめ
| 用途 | 使うSQL/コマンド |
|---|---|
| 全セッション一覧 | SELECT FROM V$SESSION WHERE USERNAME IS NOT NULL |
| ユーザー別集計 | GROUP BY USERNAME, STATUS |
| 長時間実行セッション | WHERE LAST_CALL_ET > 秒数 |
| 実行中SQLの確認 | VSESSION+VSESSION + V SESSION+VSQL結合 |
| 単一セッションの切断 | ALTER SYSTEM KILL SESSION ‘SID,SERIAL#’ IMMEDIATE |
| 複数セッションの一括切断 | PL/SQLループでKILL |
V$SESSION はOracleの運用に欠かせないビューです。定期的に確認する習慣をつけておくと、トラブルの早期発見につながります。





コメント