ORA-03113: end-of-file on communication channel は、Oracle クライアントがサーバープロセスとの通信チャンネルから予期しない終端(EOF)を受信したときに発生するエラーです。原因はインスタンスクラッシュ・ネットワーク障害・ファイアウォールタイムアウト・サーバープロセス異常終了と多岐にわたるため、正しい手順で原因を絞り込むことが重要です。
- ORA-03113 が発生する4つの主な原因と見分け方
- アラートログとトレースファイルで根本原因を調査する手順
- ファイアウォールのアイドルタイムアウトが原因のケースと対処法
- Dead Connection Detection(SQLNET.EXPIRE_TIME)の設定方法
- DISABLE_OOB・OS 側 TCP keepalive の活用
- ORA-03113 と ORA-03114 の違い
ORA-03113 とは
Oracle のクライアントとサーバーは TCP 接続(または IPC)を通じて通信します。クライアントが SQL を送信しようとしたとき、または結果セットを受信中にチャンネルが閉じられると、クライアントは EOF を受信し ORA-03113 が発生します。
ORA-03113 はあくまでクライアント側のエラーで、「接続が切れた」という結果だけを示します。なぜ切れたのかはサーバー側のログを確認しなければ分かりません。
- ORA-03113: 確立済みの接続が途中で切れた(EOF を受信)
- ORA-03114: not connected to ORACLE — そもそも接続されていないか、接続がすでにクローズされた後に操作しようとした
ORA-03113 → 切断された原因を調査。ORA-03114 → 接続状態を確認してから再接続。
発生原因4つと見分け方
原因① Oracle インスタンスのクラッシュ・シャットダウン
インスタンスがクラッシュした場合、接続していた全クライアントが同時に ORA-03113 を受信します。「一斉に切れた」場合はインスタンスを疑います。
- 見分け方:複数の接続・アプリケーションで同時にエラー発生。アラートログに ORA-00600 / ORA-07445 / shutdown などが記録されている
- 対処:インスタンスを再起動。クラッシュの場合は MOUNT → OPEN 時に自動的に Instance Recovery が実行される
原因② ネットワーク切断(物理的な障害)
ケーブル断・スイッチ障害・VPN の再接続など、物理的なネットワーク障害が原因の場合は特定のクライアントや拠点のみでエラーが発生します。
- 見分け方:同一ネットワーク上の別のクライアントでも接続不可。ping が通らない
- 対処:ネットワーク障害を解消後に再接続
原因③ ファイアウォールのアイドル接続タイムアウト(最もよくある原因)
企業環境で最もよく遭遇する原因です。ファイアウォールは一定時間パケットが流れない接続(アイドル接続)を強制切断します。このとき Oracle サーバーは「接続は生きている」と思っていますが、ファイアウォールの接続テーブルからはエントリが消えています。
次回クライアントが SQL を実行しようとすると、パケットがファイアウォールでドロップされるか、RST(リセット)が返り、ORA-03113 が発生します。
- 見分け方:長時間アイドルの後(夜間・昼休み後)に発生。短時間の接続では発生しない。再接続すれば正常に動く
- 対処:SQLNET.EXPIRE_TIME で Dead Connection Detection を設定(後述)
原因④ サーバープロセスの異常終了(ORA-00600 / ORA-07445)
Oracle の内部エラー(ORA-00600・ORA-07445)が発生すると、そのセッションのサーバープロセスが異常終了し、そのクライアントだけが ORA-03113 を受信します。
- 見分け方:特定の SQL や操作でのみ発生。他のセッションは正常。アラートログに ORA-00600 が記録されている
- 対処:Oracle サポートへの報告が必要。トレースファイルをサポートに提供する
調査手順:アラートログとトレースファイルの確認
# Oracle 11g 以降: 診断ログは ADR(Automatic Diagnostic Repository)に格納される # デフォルトパス: $ORACLE_BASE/diag/rdbms/<db_name>/<instance_name>/trace/ # アラートログの場所を SQL*Plus から確認 # SELECT value FROM v$diag_info WHERE name = 'Diag Trace'; # アラートログのパス例(Linux) ls /u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log # 最新のエラーを確認(ORA- で始まる行を抽出) tail -200 /u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log | grep -E "ORA-|Error|error|Crash|crash|shutdown" # ORA-00600 の発生確認 grep "ORA-00600" /u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log | tail -20 # インスタンスのシャットダウン履歴を確認 grep -E "Shutting down|Starting up|Instance terminated" /u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log | tail -20
# ORA-00600 / ORA-07445 が発生した場合はトレースファイルが生成される # ファイル名: <instance_name>_ora_<PID>.trc # 最新のトレースファイルを探す ls -lt /u01/app/oracle/diag/rdbms/orcl/orcl/trace/*.trc | head -10 # エラー内容の確認 grep -A 10 "ORA-00600" /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_12345.trc # ADR コマンドで診断情報を表示(adrci ツール) adrci # adrci> show incident # adrci> show problem
-- 診断ファイルのパスを SQL で確認
SELECT name, value FROM V$DIAG_INFO
ORDER BY name;
-- 主要な出力:
-- Diag Trace : アラートログとトレースファイルのパス
-- Diag Alert : アラートログ専用のパス(XML 形式)
-- Diag Incident: インシデントトレースのパス
-- 現在の接続セッション情報(切断前にセッションIDを記録しておくと調査しやすい)
SELECT sid, serial#, status, username, program,
TO_CHAR(logon_time, 'YYYY/MM/DD HH24:MI:SS') AS logon_time,
machine
FROM V$SESSION
WHERE username IS NOT NULL
ORDER BY logon_time;
ファイアウォール対策:Dead Connection Detection(SQLNET.EXPIRE_TIME)
ファイアウォールのアイドルタイムアウトが原因の場合、SQLNET.EXPIRE_TIME を設定することで解消できます。この設定により Oracle サーバーが定期的にプローブパケットをクライアントに送信し、ファイアウォールの接続テーブルをリフレッシュします。
クライアントが実際に死んでいる場合(プロセスがクラッシュしてTCP RST も返ってこない)は、プローブに応答がないためサーバープロセスを終了させ、ゴースト接続によるリソース浪費を防ぐ効果もあります。
# ファイル: $ORACLE_HOME/network/admin/sqlnet.ora # または TNS_ADMIN 環境変数で指定したディレクトリ # Dead Connection Detection を有効化(10分間隔でプローブ) SQLNET.EXPIRE_TIME = 10 # ファイアウォールのアイドルタイムアウト値より短い値を設定する # 例: ファイアウォールが 30 分でタイムアウトする場合 → 10 分に設定 # 設定値の目安: # SQLNET.EXPIRE_TIME = 0 : 無効(デフォルト) # SQLNET.EXPIRE_TIME = 10 : 10分間隔(推奨の基本設定) # SQLNET.EXPIRE_TIME = 5 : 5分間隔(より確実だがプローブ通信が増える)
# Out-of-Band break(OOB)はファイアウォールによってはブロックされる # OOB を使わないように設定する場合(サーバー・クライアント両側の sqlnet.ora に設定) DISABLE_OOB = ON # この設定が必要な典型的なシナリオ: # - ファイアウォール越しの接続で Ctrl+C キャンセルが効かない # - リモート接続でクエリのキャンセル後に ORA-03113 が発生する # ※ DISABLE_OOB = ON にすると Ctrl+C によるクエリキャンセルが遅くなる
# Oracle の SQLNET.EXPIRE_TIME に加えて OS の TCP keepalive も設定できる # TCP keepalive はファイアウォールに対して定期的に空のパケットを送り続ける # 現在の TCP keepalive 設定を確認 cat /proc/sys/net/ipv4/tcp_keepalive_time # 最初の keepalive 送信までの時間(秒、デフォルト 7200) cat /proc/sys/net/ipv4/tcp_keepalive_intvl # keepalive 間隔(秒、デフォルト 75) cat /proc/sys/net/ipv4/tcp_keepalive_probes # 失敗を判断するまでの試行回数(デフォルト 9) # ファイアウォールタイムアウトが 30 分の場合: 1800 秒より短く設定 echo 1200 > /proc/sys/net/ipv4/tcp_keepalive_time # 20分に変更(一時的) # 恒久的に設定する場合は /etc/sysctl.conf に記述 echo "net.ipv4.tcp_keepalive_time = 1200" >> /etc/sysctl.conf sysctl -p
インスタンスクラッシュの場合の対処
-- インスタンスのクラッシュ後は STARTUP コマンドで再起動 -- Oracle が自動的に Instance Recovery を実行する -- SQL*Plus で SYSDBA として接続して再起動 -- sqlplus / as sysdba -- インスタンスの状態を確認 SELECT STATUS FROM V$INSTANCE; -- STARTED / MOUNTED / OPEN -- 手動での Instance Recovery(通常は OPEN 時に自動実行) RECOVER DATABASE; -- MOUNT 状態から -- データベースをオープン ALTER DATABASE OPEN; -- ※ クラッシュ後の OPEN では SMON が自動的に前進ロールフォワードとロールバックを実行する -- → 未コミットのトランザクションは自動的にロールバックされる
アプリケーション側の対処:接続プールの再接続
アプリケーション(JDBC・OCI・ODP.NET)の接続プールは、切断された接続を保持し続けることがあります。ORA-03113 が発生した接続を破棄して再接続する設定が必要です。
- JDBC(Oracle JDBC):
oracle.jdbc.readTimeoutでタイムアウトを設定し、障害時に自動再接続する - OCI 接続プール:
OCI_ATTR_CONN_TIMEOUTでタイムアウトを設定する - Universal Connection Pool(UCP):
setValidateConnectionOnBorrow(true)で接続の有効性をチェックする - Application Continuity:Oracle 12c 以降の機能で、クラッシュや再起動後に自動的にリプレイを行い透過的に継続できる(Oracle RAC / Data Guard 環境)
まとめ:原因別の対処フロー
| 状況 | 疑われる原因 | 調査・対処 |
|---|---|---|
| 全クライアントが同時にエラー | インスタンスクラッシュ・シャットダウン | アラートログ確認 → インスタンス再起動 |
| 長時間アイドル後のみ発生 | ファイアウォールのアイドルタイムアウト | SQLNET.EXPIRE_TIME を設定して DCD を有効化 |
| 特定の SQL 実行時に発生 | ORA-00600 / ORA-07445 によるサーバープロセス異常終了 | アラートログ・トレースファイル確認 → Oracle サポートへ |
| 特定の拠点やクライアントのみ | 物理的なネットワーク障害 | ネットワーク疎通確認(ping・traceroute) |
| 再接続すれば解消する | 一時的なネットワーク揺れ・ファイアウォールタイムアウト | SQLNET.EXPIRE_TIME + DISABLE_OOB の設定 |
セッション状態の確認と強制切断についてはセッションの確認・強制切断方法完全ガイドを、リスナーの設定と障害対応についてはリスナー設定完全解説も合わせて参照してください。
