>> 連載トップページに戻る

 

基本からわかる!高性能×高可用性データベースシステムの作り方

第3回 ネットワーク経由で接続


著者紹介


日下部 明 (くさかべ あきら)

日本オラクル Oracle Database担当。Oracle GRID Centerのラインマネージャとしてオラクルの持つ最新技術をパートナー各社と共同で検証し、多くのホワイトペーパーを執筆・レビューしてきました。以後、Oracle Databaseのセキュリティ製品のリリースマネージャを担当。これらの経験を元にミッションクリティカルな案件のソリューションデザインの提案などを担当しています。著書に「これは使えるOracle新機能活用術」(翔泳社)。


第3回 ネットワーク経由で接続


連載第2回ではデータベースを作成(CREATE DATABASE)するときに最低限考慮しておかなければならないことについて解説しました。今回はOracle Databaseにネットワーク経由で接続する、というテーマを扱います。Oracleクライアントが接続に指定するパラメータはOracleサーバーの何を指しているのでしょうか。それはデータベース名でもインスタンス名でもありません。

1 Oracle Databaseサーバーのアーキテクチャ

連載第2回では、データベースを作成するときにデータベース名とインスタンス名を決めると説明しました。実はその前に行っておくことがあります。それはOracleリスナー(tnslsnr)を構成することです。OracleリスナーとはTCP/IP経由の接続リクエストを処理するプロセスであり、Oracleインスタンスのプロセス群とは独立しています。SQL*PlusなどのOracleクライアントはこのOracleリスナーに対して接続リクエストを発行することになります。

img-1

シングル・インスタンス構成でDatabase Configuration Assistant(dbca)ツールを使ってデータベースを作成するとき、Oracleインスタンスと対応付けられるOracleリスナーを指定します。また、Oracle Grid Infrastructure(GI)をインストールしている場合は、GI側のORACLE_HOMEでOracleリスナーが作成され、GIによってOracleリスナーが管理されます。

2 Oracle Net Services

Oracle Databaseでのネットワーク接続にかかわるコンポーネントを総称してOracle Net Servicesと呼びます。以前のバージョンではSQL*NetやNet8と呼ばれていたものですが、Oracle9iで改称されました。Oracle Net ServicesにはOracleの通信プロトコルやOracleリスナーが含まれます。
Oracle Clientソフトウェアをインストールすると、各種言語用のOracleクライアント・ドライバがインストールされます。Oracleクライアント・ドライバにはJDBC thinドライバ(Java)、OCI(C)、OCCI(C++)そしてODP.NET(Microsoft .NET)があります。そしてC言語用のOCIをベースにして、メジャーなほとんどの言語用のライブラリが開発されています。
また、OracleクライアントはOracleサーバーの構成には依存しません。どういうことかというと、Oracleサーバーの構成がシングル・インスタンスであるか、または高可用性構成であるOracle Real Application ClustersもしくはOracle Data Guardであるかに依存せず、共通のOracleクライアント・ソフトウェアで接続することができます。

img-2

Oracle NetプロトコルはOracle Databaseが提供されるプラットフォームの種類に依存しません。Oracleバイナリが提供されている任意のプラットフォームの組み合わせで通信することができます。Oracle Netの通信に制約がかかるのはクライアントとサーバーのバージョンの組み合わせです。バージョンが大きく離れていると通信はサポートされません。サポートされるバージョンの組み合わせの完全な情報はMy Oracle SupportのDoc ID 207303.1を参照(要サポート契約)してください。

img-3

3 接続記述子

Oracleクライアントがネットワーク経由でOracleサーバーに接続リクエストを発行するには、データベース・ユーザー名とパスワード、そしてOracleサーバーのネットワーク接続情報を指定します。これらをあわせて接続文字列(connect strings)と呼びます。このうち、Oracleサーバーのネットワーク接続情報の部分を接続記述子(connect descriptor)と呼びます。

img-4

接続記述子はDESCRIPTION=...で始まるOracleサーバーの情報で、Oracleリスナーが接続リクエストを受け付けるホスト名とポート番号、そしてOracleインスタンスが担当するサービス名を指定します。接続記述子は1行でDESCRIPTION=...と記述してもよいのですが、よく使用するものはtnsnames.oraファイルに記述し、それにエイリアスをつけておくことができます。

4 動的サービス登録

接続記述子の中にサービス名(SERVICE_NAME)を指定しましたが、これはOracleインスタンスが担当しているサービス名です。サービス名のデフォルト値はデータベース名に由来していますが、これはデータベース名ともインスタンス名とも異なる概念です。サービスの概念は後述します。
OracleリスナーとOracleデータベースは1つのサーバー上にそれぞれ複数構成することが可能です。Oracleインスタンスは自身の担当しているサービスの情報をOracleリスナーに登録します。この仕組みを動的サービス登録と呼びます。これにより、OracleリスナーはOracleインスタンスがどのサービスを担当しているかを把握し、Oracleクライアントからの接続リクエストで指定されたSERVICE_NAMEと照合することで適切なOracleインスタンスにルーティングします。
動的サービス登録はOracleインスタンスの初期化パラメータLOCAL_LISTENERを構成することで機能します。LOCAL_LISTENERが指すネットワーク・アドレスはOracleリスナーのネットワーク・アドレスです。LOCAL_LISTENERで指定したネットワーク・アドレスに対して、OracleインスタンスのLREG(Listener REGistration)プロセスがサービス情報を登録します。LOCAL_LISTENERに指定するネットワーク・アドレスは、直接指定することもできますが、tnsnames.oraファイルにエイリアスを作成することもできます。

img-5

Oracle Grid Infrastructureがインストールされていないシングル・インスタンス環境の場合、dbcaでデータベースを作成するときにOracleインスタンスに対応付けるOracleリスナーを指定しますが、ここで対応付けたOracleリスナーのアドレスを指すようにLOCAL_LISTENERとtnsnames.oraファイルが構成されます。Oracle Grid InfrastructureがインストールされているRAC環境では、GIがOracleインスタンス起動後にALTER SYSTEM文でLOCAL_LISTENERを自動的に設定します。
動的サービス登録を行うのは、Oracle Database 11g Release 2まではPMON(Process MONitor)プロセスの役割でしたが、Oracle Database 12c Release 1からは新しく導入されたLREGプロセスに移管されました。
Oracleリスナーに登録されたサービスの一覧は”lsnrctl status リスナー名”または”lsnrctl services リスナー名”で調べることができます。Oracleクライアントの接続記述子のSERVICE_NAMEに指定する名前はこのOracleリスナーに登録されたサービス名です。

4.1 サービス名のデフォルト値

サービス名はデータベース名ともインスタンス名とも異なる概念ですが、サービス名のデフォルト値はデータベース名に由来しています。CDB構成の場合、プラガブル・データベースごとにサービスを持ちます。
非CDB構成もしくはCDB構成のCDB$ROOTのデフォルト・サービス名はデータベースを作成するときに指定したDB_NAMEに由来しています。CDB$ROOTのデフォルト・サービス名は初期化パラメータSERVICE_NAMESに設定されています。SERVICE_NAMESのデフォルト値はDB_UNIQUE_NAME.DB_DOMAINであり、DB_UNIQUE_NAMEのデフォルト値はDB_NAMEです。CDB構成の各プラガブル・データベースのデフォルト・サービス名はPDB名.DB_DOMAINです。

img-6

Oracleクライアントの接続記述子のSERVICE_NAMEに、データベース名に由来するデフォルト・サービス名を指定して接続することもできますが、アプリケーションからの接続にはデフォルト・サービス名は使用しません。デフォルト・サービス名はOracle Enterprise Managerなどの管理ツールからの接続に使用し、アプリケーションからの接続には追加のサービスを構成します。

4.2 サービス

Oracle8までは、接続記述子に指定するのはSERVICE_NAMEではなく、Oracleインスタンス識別子であるSIDでした。つまり、OracleクライアントはOracleインスタンス名を指定して接続するという概念でした。Oracle8iから、SIDの代わりにSERVICE_NAMEとINSTANACE_NAMEが導入されました。Oracle9iで導入されたOracle Real Application Clustersや、その前身であるOracle Parallel Serverは1つのデータベースを複数のOracleインスタンスがマウントする共有ディスク・アーキテクチャです。複数あるOracleインスタンスはクラスタの中でそれぞれ一意な名前(SIDおよびINSTANCE_NAME)を持っていますが、OracleクライアントはどのOracleインスタンスに接続してもすべてのデータにアクセスすることができ、同じSQLを実行することができます。クラスタが複数のOracleインスタンスで構成されていても、Oracleクライアントは1つのデータベースに接続しているということを抽象化する階層としてSERVICE_NAME(S)が導入されました。Oracleクライアントの接続記述子は1つのサービスを指定して接続リクエストを発行するので単数形のSERVICE_NAMEですが、1つのOracleインスタンスは複数のサービスを担当できるので、初期化パラメータSERVICE_NAMESは複数形です。

img-7

Oracle Database 10gではサービスの概念が拡張され、ワークロードを抽象化する概念となりました。データ・ディクショナリにサービスを登録し、サービスごとにアクティビティを観測できるようになりました。これを自動ワークロード管理と呼びます。そしてOracle Database 10g以後、サービスの属性を追加するという形で機能拡張されてきました。サービスの属性を設定できるのは追加で作成したサービスに対してのみであり、データベース名に由来するデフォルト・サービスにはできません。そのため、アプリケーションからの接続には追加のサービスを作成します。

img-8

Oracle Database 10g以降では、サービスを追加するには初期化パラメータSERVICE_NAMESを変更するのではなく、データ・ディクショナリに登録するという操作を行います。Oracle Grid Infrastructureがインストールされていないシングル・インスタンス環境ではPL/SQLパッケージのDBMS_SERVICEを使用します。Oracle Grid Infrastructureがインストールされている環境ではsrvctlコマンドを使用します。サービスを追加するには、作成と起動という2つの工程があります。DBMS_SERVICEやsrvctlでサービスを追加すると、データ・ディクショナリにそのサービスが現れます。次の例ではプラガブル・データベース”pdb”に対し”pdbsvc1”というサービスを追加しています。

SQL> alter session set container=pdb;
セッションが変更されました。
SQL> execute DBMS_SERVICE.CREATE_SERVICE('pdbsvc1','pdbsvc1');
PL/SQLプロシージャが正常に完了しました。
SQL> execute DBMS_SERVICE.START_SERVICE('pdbsvc1',NULL);
PL/SQLプロシージャが正常に完了しました。
SQL> SELECT con_id,name,network_name FROM v$active_services;

    CON_ID NAME                           NETWORK_NAME
---------- ------------------------------ ------------------------------
         3 pdb                            pdb
         3 pdbsvc1                        pdbsvc1

追加されたサービスは、動的サービス登録の仕組みによってOracleリスナーに登録されます。Oracleリスナーに登録されるサービス名は初期化パラメータDB_DOMAINで修飾されることに注意してください。Oracleクライアントの接続記述子に指定するサービス名は、このOracleリスナーに登録されたサービス名です。

$ lsnrctl status LISTENER
(中略)
サービス"pdb.jp.oracle.com"には、1件のインスタンスがあります。
  インスタンス"sidb18a"、状態READYには、このサービスに対する1件のハンドラがあり ます...
サービス"pdbsvc1.jp.oracle.com"には、1件のインスタンスがあります。
  インスタンス"sidb18a"、状態READYには、このサービスに対する1件のハンドラがあり ます...

データ・ディクショナリに登録されたサービスごとに消費したリソースが記録され、AWRレポートでも確認することができます。

img-9

自動ワークロード管理が実装されると、データベース・リソース・マネージャはサービスを単位としてもリソース制限をかけられるようになりました。また、複数のOracleインスタンスから1つのデータベースをマウントするRACでは、どのOracleインスタンスがどのサービスを担当するかという概念が発生します。複数のOracleインスタンスに対するロードバランスも自動ワークロード管理の範疇です。また、RACに限らず、アクティブ/スタンバイ型クラスタやOracle Data Guardなどの高可用性構成では障害発生時のサービスのフェイルオーバーも重要です。サービスの可用性については次回のテーマとします。

5 典型的なエラーとトラブルシューティング

Oracleクライアントから接続しようとするときに発生する典型的なエラーには以下のものがあります。これらのエラーのトラブルシューティングについて見ていきましょう。

  • ORA-12154: TNS: 指定された接続識別子を解決できませんでした
  • ORA-12541: TNS: リスナーがありません
  • ORA-12514: TNS: リスナーは接続記述子でリクエストされたサービスを現在認識していません

5.1 ORA-12154: TNS: 指定された接続識別子を解決できませんでした

接続記述子をtnsnames.oraファイルに記述し、Oracleクライアントの接続文字列にエイリアスを指定した場合に起こりえるエラーです。根本的には接続文字列のエイリアスとtnsnames.oraファイルのエイリアスが一致していないことによるものですが、何度見返しても一致しているのになぜこのエラーが出るのか、という場合があります。それはtnsnames.oraファイルの場所が想定したところと違うことに原因があります。
tnsnames.oraファイルの位置はデフォルトではOracleソフトウェアをインストールしたORACLE_HOME/network/admin/ディレクトリです。複数のOracleソフトウェアをインストールしている場合、ORACLE_HOMEの数だけtnsnames.oraファイルがあることになります。また、tnsnames.oraファイルを含むOracle Netの設定ファイルのディレクトリは環境変数TNS_ADMINでデフォルトの位置から変更することができます。たとえば複数バージョンのOracleクライアントをインストールしているが、tnsnames.oraファイルを共通にするためにTNS_ADMINを設定している場合が考えられます。

img-10

接続文字列に指定したエイリアスが、Oracleクライアント・ドライバが実際に参照しているtnsnames.oraファイルに記述されているかを確認してください。

5.2 ORA-12541: TNS: リスナーがありません

この場合、Oracleクライアント・ドライバは接続文字列を解釈し、Oracleサーバーに接続リクエストを発行しています。しかし、接続記述子に指定したネットワーク・アドレスにはOracleリスナーが起動していなかったというエラーです。

img-11

接続記述子に指定したネットワーク・アドレスと、OracleリスナーがLISTENしているネットワーク・アドレスが一致しているかを確認してください。また、”lsnrctl status リスナー名”でOracleリスナーが起動しているかを確認してください。

5.3 ORA-12514: TNS: リスナーは接続記述子でリクエストされたサービスを現在認識していません

この場合、Oracleクライアントからの接続リクエストはOracleリスナーに届いています。しかし、接続記述子のSERVICE_NAMEで指定したサービスがOracleリスナーに登録されていないというエラーです。

img-12

デフォルトのサービスではなく、srvctlやDBMS_SERVICEで追加したサービスに接続する場合、サービスを作成しただけでなく、起動されているかを確認してください。起動しているサービスはV$ACTIVE_SERVICESビューで確認することができます。また、Oracle Net上で認識されるサービス名は初期化パラメータDB_DOMAINで修飾されることに注意してください。Oracleリスナーに登録されたサービスは”lsnrctl status リスナー名”で確認することができます。
V$ACTIVE_SERVICESビューにサービスが現れているのにOracleリスナーに登録されていない場合は、初期化パラメータLOCAL_LISTENERが該当するOracleリスナーを指しているかを確認してください。複数のOracleリスナーを作成している場合、LOCAL_LISTENERが指しているOracleリスナーと接続記述子が指しているOracleリスナーが異なっていることも考えられます。また、Oracleインスタンス起動後にOracleリスナーを再起動した場合は、30秒待ってからOracleリスナーに登録されたサービスを確認してみてください。Oracleインスタンスはサービス構成に変更があったとき、および30秒ごとにOracleリスナーにサービス情報を更新しています。

連載第3回はネットワーク経由でOracle Databaseに接続するというテーマを扱いました。Oracleクライアントはサービスに接続するという概念になっています。次回はこの応用編です。クラスタ構成などの高可用性構成でのOracle Netの構成について解説します。データベース・サーバー側が高可用性構成になっていても、データベース・クライアント側がそれに対応していなければ効果が激減してしまいます。Oracle Netは高可用性構成に対応しています。