[Oracle] OEMでインスタンスを再起動するとORA-12514エラーが発生 | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

Oracle Enterprise Managerでインスタンスの構成などを変更した後、設定変更を適用するためにインスタンスを再起動すると、

ORA-12514: TNS:listener could not resolve SERVICE_NAME given in connect descriptor
(ORA-12514: TNS: リスナーは接続記述子にあるSERVICE_NAMEを解決できませんでした。)

というエラーが発生し、インスタンスを起動できなくなることがあります。

それまで正常に接続してたにもかかわらず、再起動するとこのようなエラーが発生するのです。

このエラーは、SQL*Plusでも起こることがあります。

sqlplus "sys/change_on_install@orcl as sysdba"

というようにOracle Net接続識別子を指定してインスタンスに接続しようとする際、インスタンスが起動していれば正常に接続できるのですが、インスタンスが停止していればORA-12514が発生します。

要するにOracle Enterprise Managerにしても、SQL*Plusにしても、インスタンスが停止した状態で接続しようとするとORA-12514が発生するようです。

こういうとき、真っ先に疑うのはローカル・ネーミング・メソッドの構成、つまりtnsnames.oraの構成ミスですが、インスタンスが起動していれば接続できるのですから、この設定がおかしいはずはありません。

だとすると次に疑わしいのはリスナーの構成なのですが...

まずlistener.oraを確認すると、以下のようになっています。

# LISTENER.ORA Network Configuration File: C:\oracle\ora92\network\admin\listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = ORCLSERVER)(PORT = 1521))
      )
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
      )
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\oracle\ora92)
      (PROGRAM = extproc)
    )
  )

SID_LIST_LISTNERにデータベース・サービスの設定がありません...

だから「SERVICE_NAMEを解決できませんでした。」なんてことを言われるのです。

このようなときは、テキストエディターでもNet Mangerでもなんでもいいから、SID_LIST_LISTNERにデータベース・サービスを追加してやればいいのです。

# LISTENER.ORA Network Configuration File: C:\oracle\ora92\NETWORK\ADMIN\listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ORCLSERVER)(PORT = 1521))
    )
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\oracle\ora92)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = ORCL)
      (ORACLE_HOME = C:\oracle\ora92)
      (SID_NAME = ORCL)
    )
  )
こうするとインスタンスが起動していようがいまいが、問題なく接続できるようになります。

一件落着。めでたしめでたし...じゃないです^^

確かに上記のようにリスナーの構成でデータベース・サービスを追加してやれば、問題は解消されるのですが、では、リスナーの構成にデータベース・サービスが抜けているとき、インスタンスが起動していれば問題がなくて、インスタンスが停止していればエラーになるというのは何故なんでしょうか?

「Oracle9i Net Services管理者ガイド」を見ると、その答えがありました。

リスナーでサポートされるデータベース・サービスはあらかじめlistener.oraに設定する(静的サービス構成)か、各インスタンスのPMONプロセスによって動的に登録(サービス登録)されるかのいずれかによって構成されるということのようです。

つまり、listener.oraに設定していれば問題がないのはもちろんのこと、listener.oraに設定していなくてもインスタンスが起動していれば動的に登録されるから問題ないということになるのです。

実際に、listener.oraに設定していない状態でリスナーコントローラー(lsnrctl)のservicesコマンドでサービスの状況を確認してみると、

まず、インスタンスを停止しているときは、

LSNRCTL> services
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ORCLSERVER)(PORT=1521)))に接続中
サービスのサマリー...
サービス"PLSExtProc"には、1件のインスタンスがあります。
  インスタンス"PLSExtProc"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "DEDICATED" 確立:0 拒否:0
         LOCAL SERVER
コマンドは正常に終了しました。
LSNRCTL>

となっていて、データベース・サービスが存在しないことがわかります。

そこで、インスタンスを起動して再度確認してみると、

LSNRCTL> services
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=ORCLSERVER)(PORT=1521)))に接続中
サービスのサマリー...
サービス"ORCL"には、1件のインスタンスがあります。
  インスタンス"ORCL"、状態READYには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "DEDICATED" established:0 refused:0 state:ready
         LOCAL SERVER
サービス"ORCLXDB"には、1件のインスタンスがあります。
  インスタンス"ORCL"、状態READYには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "D000" 確立:0 拒否:0 現行:0 最大:1002 状態:ready
         DISPATCHER <machine: X-GLADIUS, pid: 1648>
         (ADDRESS=(PROTOCOL=tcp)(HOST=ORCLSERVER)(PORT=2272))
サービス"PLSExtProc"には、1件のインスタンスがあります。
  インスタンス"PLSExtProc"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
    ハンドラ:
      "DEDICATED" 確立:0 拒否:0
         LOCAL SERVER
コマンドは正常に終了しました。
LSNRCTL>

おお、データベース・サービスが登録されているではないですか。

これで謎が解けました。

ちなみに、「Oracle9i Net Services管理者ガイド」を見ると、さらっと書いてありました...

Oracle Enterprise Manager のツールでは、listener.ora ファイルに静的サービス構成が必要です。

と。

要はインスタンスが起動している状態で操作する分には必要ないが、インスタンスの停止/起動を行うには必要ということですね。

今度こそ、一件落着^^