Oracleデータベースで「テーブルが更新できない」「クエリが返ってこない」といった症状の原因の多くはロック競合です。本記事では、ロックの状態を確認するSQLと、ロックを解除(セッションのKILL)する手順を解説します。
1. Oracleのロックとは {#about-lock}
Oracleでは、DML操作(INSERT・UPDATE・DELETE)を実行すると行レベルのロックが自動的に取得されます。このロックはCOMMITまたはROLLBACKが実行されるまで保持されます。
ロック競合が発生すると、後から同じ行を操作しようとしたセッションはロックが解放されるまで待機します。長時間のロック保持はシステムの停止につながるため、迅速な原因特定と対処が重要です。
ロック競合が起きる典型的なケース:
- UPDATEしたままCOMMITを忘れている
- バッチ処理が途中で止まっている
- アプリケーションのトランザクション管理の不具合
2. ロック待ちのセッションを確認する {#check-lock-wait}
以下のSQLで、現在ロック待ちになっているセッションを一覧表示できます。
SELECT
s.SID,
s.SERIAL#,
s.USERNAME,
s.STATUS,
s.MACHINE,
s.PROGRAM,
s.LOGON_TIME,
s.WAIT_CLASS,
s.EVENT,
s.SECONDS_IN_WAIT -- 待機している秒数
FROM
V$SESSION s
WHERE
s.WAIT_CLASS = 'Application'
AND s.EVENT LIKE '%lock%'
ORDER BY
s.SECONDS_IN_WAIT DESC;SECONDS_IN_WAITが大きいセッションほど長時間待機しており、問題が深刻です。
3. ロックを保持しているセッションを特定する {#find-blocker}
ロック待ちを起こしている「ブロッカー(原因)」と「ウェイター(被害者)」を一覧表示します。
SELECT
w.SID AS WAITER_SID, -- 待機中のSID
w.SERIAL# AS WAITER_SERIAL,
w.USERNAME AS WAITER_USER,
b.SID AS BLOCKER_SID, -- ブロックしているSID
b.SERIAL# AS BLOCKER_SERIAL,
b.USERNAME AS BLOCKER_USER,
b.MACHINE AS BLOCKER_MACHINE,
b.PROGRAM AS BLOCKER_PROGRAM,
b.LOGON_TIME AS BLOCKER_LOGON,
w.SECONDS_IN_WAIT
FROM
V$SESSION w
JOIN V$SESSION b
ON w.BLOCKING_SESSION = b.SID
WHERE
w.BLOCKING_SESSION IS NOT NULL
ORDER BY
w.SECONDS_IN_WAIT DESC;出力のポイント:
BLOCKER_SID/BLOCKER_SERIALがロックを保持しているセッションBLOCKER_MACHINEでどの端末・サーバーからの接続かを把握できるBLOCKER_LOGONで何時からのセッションかを確認できる
4. 実行中のSQLを確認する {#check-sql}
ブロッカーが何のSQLを実行(または実行後放置)しているか確認します。
SELECT
s.SID,
s.SERIAL#,
s.USERNAME,
s.STATUS,
sq.SQL_TEXT, -- 実行中のSQL
sq.LAST_ACTIVE_TIME
FROM
V$SESSION s
LEFT JOIN V$SQL sq
ON s.SQL_ID = sq.SQL_ID
WHERE
s.SID = 123; -- ブロッカーのSIDを指定STATUS = 'INACTIVE'かつロックを保持している場合は、COMMIT/ROLLBACKを忘れた状態であることが多いです。
5. ロックを解除する(セッションのKILL) {#kill-session}
ロックを解除するにはセッションをKILLします。対象セッションのSIDとSERIAL#が必要です。
KILLコマンド
ALTER SYSTEM KILL SESSION 'SID,SERIAL#';実行例:
ALTER SYSTEM KILL SESSION '123,456';IMMEDIATEオプション(即時終了)
通常のKILLはOracle内部でのクリーンアップを待つ場合があります。すぐに解放したい場合はIMMEDIATEを付けます。
ALTER SYSTEM KILL SESSION '123,456' IMMEDIATE;注意: KILL SESSIONを実行するには
ALTER SYSTEM権限(通常はDBA権限)が必要です。また、KILLによりそのセッションのトランザクションはROLLBACKされます。業務影響を確認した上で実行してください。
セッションをKILLする前の確認チェックリスト
- KILLするセッションが正しいか(SID・SERIAL#・USERNAME・MACHINEを再確認)
- KILL後にROLLBACKされる更新データの業務影響を確認
- 可能であれば、セッションを持つ担当者・アプリへの連絡
6. DDLロック(テーブルロック)を確認する {#ddl-lock}
ALTER TABLEなどのDDLがロックを保持している場合はV$LOCKED_OBJECTとDBA_OBJECTSを使います。
SELECT
lo.SESSION_ID,
s.SERIAL#,
s.USERNAME,
s.MACHINE,
lo.ORACLE_USERNAME,
lo.LOCKED_MODE, -- ロックモード(2=行共有、3=行排他、など)
do.OBJECT_NAME, -- ロック対象のオブジェクト名
do.OBJECT_TYPE
FROM
V$LOCKED_OBJECT lo
JOIN DBA_OBJECTS do
ON lo.OBJECT_ID = do.OBJECT_ID
JOIN V$SESSION s
ON lo.SESSION_ID = s.SID
ORDER BY
lo.SESSION_ID;LOCKED_MODEの値と意味:
| 値 | ロックモード |
|---|---|
| 2 | Row Share(RS) |
| 3 | Row Exclusive(RX) — 通常のDML |
| 4 | Share(S) |
| 5 | Share Row Exclusive(SRX) |
| 6 | Exclusive(X) — DDL |
7. まとめ:ロック対応の手順フロー {#summary}
【STEP 1】 ロック待ちセッションを確認
→ V$SESSION(WAIT_CLASS = 'Application')
【STEP 2】 ブロッカーを特定
→ V$SESSION の BLOCKING_SESSION 列
【STEP 3】 ブロッカーが実行中のSQLを確認
→ V$SESSION + V$SQL
【STEP 4】 ロックを解除
→ ALTER SYSTEM KILL SESSION 'SID,SERIAL#' IMMEDIATE;用途別クエリまとめ:
| 目的 | 使うビュー |
|---|---|
| ロック待ちセッションの確認 | V$SESSION |
| ブロッカー(原因)の特定 | V$SESSION(BLOCKING_SESSION列) |
| 実行中SQLの確認 | V$SESSION + V$SQL |
| オブジェクトレベルのロック確認 | V$LOCKED_OBJECT + DBA_OBJECTS |
| セッションのKILL | ALTER SYSTEM KILL SESSION |
まとめ
Oracleのロック対応は「待機セッションの確認 → ブロッカーの特定 → SQLの確認 → KILLの判断」という流れが基本です。
焦って誤ったセッションをKILLしないよう、SID・SERIAL#・USERNAME・MACHINEを必ず確認してから実行しましょう。
関連記事:







コメント