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

 

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

第4回 高可用性構成でのOracle Net構成(1)


著者紹介


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

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


第4回 高可用性構成でのOracle Net構成(1)


連載第3回ではOracle Databaseにネットワーク経由で接続する、というテーマを扱いました。Oracleサーバーがクラスタ構成などの高可用性構成をとっている場合、Oracleクライアントの設定はどのようになっているべきでしょうか。第4回はOracleサーバーの障害を想定したOracle Netの設定について説明します。


1 Oracleサーバーの高可用性構成

Oracleサーバーに障害が発生することを想定し、予備のサーバーに自動的にフェイルオーバーさせる仕組みがあります。その実装には様々なものがありますが、もっとも古くからあるのはサードパーティー製のクラスタウェアを使用し、シングル・インスタンス構成のOracleサーバーを別のサーバーで起動させるHAクラスタです。これはアクティブ・スタンバイ・クラスタやアクティブ・パッシブ・クラスタと呼ばれることもあります。クラウド環境で仮想マシンごと別の物理サーバーにフェイルオーバーする仕組みも一種のHAクラスタです。そして、Oracle9iで共有ディスク・共有メモリ型の全ノードがアクティブなクラスタであるOracle Application Clustersと、REDOログ情報をリモートのOracleサーバーに転送してレプリケーションを行うOracle Data Guardが実装されました。

img-1

1.1 HAクラスタ

複数のサーバーにクラスタウェアをインストールし、クラスタウェアは相互に稼働を監視しています。Oracleソフトウェアはシングル・インスタンス構成のOracle Databaseをインストールします。クラスタウェアはOracleリスナーのリスニング・ポイントになる仮想IPアドレス(Virtual IP address: VIP)とOracleリスナー、そしてOracleインスタンスの稼働も監視しています。クラスタを構成する各ノードは共通のストレージ・デバイスにアクセスできるようになっています。Oracleインスタンスが稼働しているサーバーに障害が発生すると、VIPとOracleリスナー、そしてOracleインスタンスをセットで待機サーバーに起動させようとします。

VIPとOracleリスナーがセットで待機サーバーにフェイルオーバーされるので、Oracleクライアントから見るとOracleサーバーのIPアドレスは変わっていないように見えます。

img-2

1.2 Oracle Real Application Clusters

Oracle Real Application ClustersはOracle9iで導入された、共有ディスク・共有メモリ型の全ノードがアクティブなOracle Databaseのクラスタ構成です。クラスタウェアとしてOracle Grid Infrastructureをインストールし、すべてのノードは相互に監視されています。RACを構成するすべてのOracleインスタンスは同一のデータベースをマウントしており、すべてのデータにアクセスすることができます。そして複数のOracleインスタンスは同一のサービスを担当することができます。

RACはすべてのノードで個別のVIPが起動しており、それに対応するOracleリスナーが稼働しています。そのため、Oracleクライアントから見ると複数のリスニング・ポイントがあるように見えます。

img-3

Oracleサーバーに障害が発生すると、障害が発生したノードのOracleインスタンスはクラスタから切り離されます。すべてのノードであらかじめOracleインスタンスが起動しているため、障害が発生したOracleインスタンスを別のノードで再起動するのではなく、クラスタから切り離すだけです。

また、Oracleリスナーもすべてのノードであらかじめ起動しているので、別のノードで再起動させるわけではありません。障害ノードのVIPは別の正常ノードにフェイルオーバーします。しかし、このフェイルオーバーしたVIPではOracleリスナーは接続リクエストを受け付けません。その理由は後述します。

1.3 Oracle Data Guard

Oracle Data GuardはOracle9iで導入された、データベースのレプリケーション構成です。プライマリ・データベースでの更新情報(REDOログ)をスタンバイ・データベースに転送し、そのREDOログを使ってリカバリし続けることでプライマリ・データベースと同じ内容になります。通常、スタンバイ・データベースのOracleインスタンスはデータベースをMOUNT状態にしてリカバリしています。そのためスタンバイ・データベース側ではデータにアクセスすることはできません。しかし、Oracle Database 11gで導入されたActive Data Guardでは、スタンバイ・データベースでリカバリを継続しながらもREAD ONLYでOPENできるようになりました。

Data Guardのプライマリ・データベースとスタンバイ・データベースの役割の変換は管理者による操作になるのですが、Data Guard BrokerとObserverを構成することで障害発生時にも自動的に変換することができます。Active Data Guardの場合、スタンバイ・データベースはREAD ONLYでOPENしているのですが、Oracle Grid Infrastructureと組み合わせることでREAD ONLY用のサービスとREAD WRITE用のサービスを切り替えることもできます。Data GuardはRACと組み合わせて使用することができます。

img-4

プライマリ・データベースとスタンバイ・データベースは同一データセンター内でも遠隔地でも構成することができます。Oracleインスタンスが稼働するノードごとにOracleリスナーがあるので、Oracleクライアントから見ると複数のリスニング・ポイントがあるように見えます。

2 複数のリスニング・ポイントに対する接続記述子

連載第3回ではOracleクライアントの接続記述子の基本的な構成を解説しました。そこではOracleリスナーのリスニング・ポイントが1つの場合を想定していました。リスニング・ポイントが複数ある場合、接続リクエストのフェイルオーバーを設定することができます。

img-5

接続記述子に複数のADDRESS句を記述しFAILOVER=ONを指定すると、接続リクエストのフェイルオーバーが可能になります。1つ目のADDRESS句に対する接続リクエストが失敗すると、2つ目のADDRESS句に接続リクエストを発行します。この仕組みを接続時フェイルオーバーと呼びます。FAILOVERの設定はデフォルトでONなので、明示的に記述しなくとも接続時フェイルオーバーは有効です。

また、接続リクエストを発行するADDRESS句の順序を制御するのがLOAD_BALANCEです。デフォルトはOFFで、ADDRESS句を上から記述された順に接続リクエストを試行します。ONの場合はランダムな順序で接続リクエストを試行します。ONの場合、複数あるOracleリスナーに対する負荷分散になり、この仕組みをクライアント側接続ロードバランスと呼びます。ただし、Oracleクライアントが実際にOracleサーバー・プロセスとTCPコネクションを生成するアドレスはクライアント側接続ロードバランスで決まるとは限りません。Oracleリスナーは接続リクエストを別のOracleリスナーにリダイレクトする場合があり、コネクションの確立はサーバー側接続ロードバランスという仕組みで行われます。

3 Oracle Grid InfrastructureのVIPとOracleリスナーの構成

Oracle Grid InfrastructureはOracle Real Application Clustersを稼働させるためのクラスタウェアです。その前身となるOracle Cluster Ready ServicesがOracle Database 10gで導入され、その後Oracle Clusterwareと名前を変え、Oracle Database 11gRelease 2にてOracle Grid Infrastructureとなりました。その間、Oracle Automatic Storage Managementの階層の取り込みや、VIPとOracleリスナーの構成に変更がありました。本稿執筆時点の最新版はOracle Database 18cですが、VIPとOracleリスナーの構成が現在の形になったのはOracle Grid Infrastructure 11g Release 2です。

Oracle Grid Infrastructureをインストールすると、2種類のVIPと2種類のOracleリスナーが構成されます。それぞれのVIPとOracleリスナーは1対1のセットで構成されます。

img-6

1種類目のVIPとOracleリスナーは、各ノードに構成されるノードVIPとローカル・リスナーです。ローカル・リスナーはノードVIPで接続リクエストをリスニングしています。各ノードにOracleインスタンスを構成したとき、初期化パラメータLOCAL_LISTENERはノードVIPでリスニングしているローカル・リスナーを指します。シングル・インスタンス構成でもRAC構成でも、OracleインスタンスはLOCAL_LISTENERで指定されたOracleリスナーに自身の担当するサービス情報を登録し、このOracleリスナーでセッションを確立します。

2種類目のVIPとOracleリスナーは、クラスタのいずれかのノードで起動しているSCAN(Single Client Access Name) VIPとSCANリスナーです。SCANリスナーはSCAN VIPで接続リクエストをリスニングしています。SCAN VIPとSCANリスナーはデフォルトで3つ構成されます。また、複数あるSCAN VIPは1つのSCANホスト名に対応付けられます。しかし、1つのホスト名に複数のIPアドレスを対応付けるのは/etc/hostsファイルの設定ではできないため、DNSサーバーが必要になります。

そして、Oracleインスタンスの初期化パラメータREMOTE_LISTENERはSCAN VIPでリスニングしているSCANリスナーを指します。そのため、クラスタ上のすべてのOracleインスタンスはSCANリスナーに対して自身の担当するサービス情報を登録することになります。Oracleクライアントの接続記述子にはSCANリスナーに対して接続リクエストを発行するようにADDRESS句を記述するのですが、SCANリスナー自体はセッション確立を行いません。ここで、サーバー側接続ロードバランスという仕組みが働きます。

4 サーバー側接続ロードバランス

Oracle Grid Infrastructure上のすべてのOracleインスタンスはREMOTE_LISTENERがSCANリスナーを指しています。そのため、SCANリスナーにはすべてのOracleインスタンスのサービス情報が集まります。SCANリスナーに対してlsnrctl statusコマンドもしくはlsnrctl servicesコマンドを発行すると、各サービスをどのOracleインスタンスが担当しているかを見ることができます。REMOTE_LISTENERで登録される情報には、Oracleインスタンスがどのサービスを担当しているかだけではなく、負荷とLOCAL_LISTENERも登録されます。

img-7

Oracleクライアントからの接続リクエストがSCANリスナーに届くと、該当サービスを担当するOracleインスタンスの候補から負荷を考慮し、接続先のOracleインスタンスを決定します。そして、そのOracleインスタンスに紐づけられたローカル・リスナーに対して接続リクエストをリダイレクトします。各ノードのローカル・リスナーはリダイレクトされてきた接続リクエストを処理し、Oracleインスタンスとのセッションを確立します。

つまり、Oracleリスナーには2つの役割があり、REMOTE_LISTENERに指定されたSCANリスナーは接続リクエストをリダイレクトするためのもので、セッションを確立するのはLOCAL_LISTENERで指定されたローカル・リスナーです。

Database Configuration Assistant(dbca)ツールでOracle Grid Infrastructure上にデータベースを作成すると、クラスタ管理のリソースとしてOracleデータベースとOracleインスタンスが登録されます。すると、Oracle Grid InfrastructureはOracleインスタンスをオープンした後にLOCAL_LISTENERとREMOTE_LISTENERを自動的にセットするようになります。

複数あるSCANリスナーはすべて同じ役割を担っており、複数あることで接続リクエストを受けるリスニング・ポイントの可用性を高めています。

5 SCANリスナーと接続記述子

SCANリスナーはOracle Grid Infrastructure 11g Release 2で導入されたものですが、そこで使用されているSCAN VIPの仕組みはDNSで1つのSCANホスト名を複数のIPアドレスに対応付けています。Oracle Client 11g Release 2からは、接続記述子にSCANホスト名を記述することに対応しています。

img-8

接続記述子にSCANホスト名を記述すると、DNSから複数のSCAN IPアドレスを引きます。1つのSCANホスト名は複数のSCAN VIPに解釈され、接続時フェイルオーバーとクライアント側接続ロードバランスを有効にすることができます。SCANリスナーに対してクライアント側接続ロードバランスを設定しても、実際の接続先はサーバー側接続ロードバランスで決定されることに注意してください。

6 ノード障害とVIP/Oracleリスナーのフェイルオーバー

Oracle Grid Infrastructure上の各VIPとOracleリスナーはクラスタ・リソースとして管理されており、ノードに障害が発生するとフェイルオーバーが試行されます。しかしその挙動はSCAN VIP/SCANリスナーとノードVIP/ローカル・リスナーで異なります。

6.1 SCAN VIP/SCANリスナー

SCAN VIPとSCANリスナーはOracleクライアントからの接続リクエストを受けるリスニング・ポイントとして機能しますが、その役割はサーバー側接続ロードバランスでリダイレクトするときだけです。SQLを実行するためのOracleクライアントとのTCPコネクションはノードVIPと確立されます。SCAN VIPとSCANリスナーの稼働しているノードに障害が発生すると、そのノードのSCAN VIPとSCANリスナーのセットが別の正常ノードにフェイルオーバーされます。そして、障害を起こしていたノードが復旧しクラスタに参加すると、SCAN VIPとSCANリスナーのセットの一部がフェイルバックします。SCAN VIPとSCANリスナーのセットは特定のノードに紐づいておらず、クラスタのどのノードでも起動することができます。

img-9

SCAN VIPとSCANリスナーのセットがフェイルオーバー/フェイルバックしている間は、ネットワーク上にそのSCANリスナーが存在しない時間帯ができます。しかし、その瞬間にOracleクライアントから接続リクエストが来たとしても、接続時フェイルオーバーで別のSCANリスナーを試行することができます。SCAN VIPとSCANリスナーのセットが複数起動しているのは、ノード障害時のSCANリスナーの可用性を高めるためです。

6.2 ノードVIP/ローカル・リスナー

ノードVIPとローカル・リスナーはOracleクライアントとのセッションを確立する役割を担います。SCAN VIPとSCANリスナーのセットとは異なり、ノードVIPとローカル・リスナーは特定のノードに紐づいています。ノードVIPとローカル・リスナーの稼働しているノードに障害が発生すると、フェイルオーバーするのはノードVIPだけです。クラスタの各ノードには固有のローカル・リスナーが稼働しており、ノード間で移動するということはありません。また、ノードVIPはフェイルオーバーしますが、移動した先のノードのローカル・リスナーではそのノードVIPを使用してリスニングはしません。各ノードのローカル・リスナーがリスニングするのは各ノード固有のノードVIPだけです。ではなぜノードVIPがフェイルオーバーするかというと、TCPコネクションを速やかに「切断」するためです。

img-10

TCP/IPはデータを送信すると、その応答を待つという動作をします。ネットワーク上に通信相手となるIPアドレスが存在していると、速やかに何らかの応答が返ってきます。しかし、ノード障害などで該当IPアドレスがネットワークから消失すると、応答を「待つ」という状態になり、障害検出時間に影響します。そこで、ノードVIPがフェイルオーバーすると、そのノードVIPを使用するソケットがないのでTCP通信に対して即座にRSTで応答し、TCPコネクションを切断することができます。ノードVIPがフェイルオーバーした先でローカル・リスナーがリスニングしていなくとも、そのノードVIPに接続リクエストが来てしまった場合はすみやかに接続時フェイルオーバーで接続リクエストを再試行できます。

なぜフェイルオーバーしたノードVIPではセッションを確立させないのでしょうか。仮に、ノードVIPがフェイルオーバーした先のローカル・リスナーでリスニングした場合を考えてみましょう。この場合、フェイルオーバーしたVIPで接続リクエストを処理しセッションを確立するということです。一見すると問題なさそうに見えますが、障害ノードが復旧し、クラスタに参加するときに問題が発生します。障害ノードが復旧すると、ノードVIPをもとのノードにフェイルバックさせることになります。このとき、このフェイルオーバーしたノードVIPでセッションを確立していたTCPコネクションを切断しなければなりません。正常にトランザクションを実行できるセッションを切断するのは影響が大きいため、フェイルオーバーしたノードVIPではセッションを確立しないようになっています。そのため、障害ノードが復旧したらいつでもノードVIPをフェイルバックさせることができます。

2種類のVIPとOracleリスナーは、フェイルオーバーとフェイルバックの両方の影響を考慮して異なる挙動を示します。

7 接続時フェイルオーバーと接続リトライ

Oracle Real Application Clustersは複数のOracleインスタンスが同一のOracleデータベースをマウントしており、どのOracleインスタンスに接続しても同じSQLを実行することができます。複数のOracleインスタンスは同じサービスを起動させておくことができ、OracleクライアントはどのOracleインスタンスに対しても同じサービス名を指定して接続できます。そのため、RACを構成するOracleサーバーに障害が発生し、別のOracleインスタンスに接続リクエストを発行してもすぐに接続することができます。

これに対し、HAクラスタやRAC One NodeそしてData Guardのように、障害を検出したら待機サーバー側でサービスを起動させる構成の場合、障害が発生してからサービスが起動するまで、ネットワーク上に該当サービスが存在しない時間帯ができることになります。そのため、OracleクライアントがOracleサーバーの障害を検出し、接続リクエストのフェイルオーバーを実施しても、待機サーバー側でサービスが起動するまでは接続リクエストが失敗することになります。このような状況に対処するために、接続時フェイルオーバーには接続リクエストの発行する間隔を制御する仕組みがあります。

7.1 接続リクエストのタイムアウト

Oracleサーバーの障害に対する自動フェイルオーバーのために、一般的にはクラスタウェアで管理させます。Oracle Grid InfrastructureはノードVIPとSCAN VIPをOracleリスナーと関連付けて管理しており、ノード障害時にはVIPが正常ノードにフェイルオーバーすることを説明しました。クラスタを構成する一部のノードに障害が発生しても、各VIPはクラスタのいずれかのノードで起動しているため、Oracleクライアントからの接続リクエストに一瞬で応答します。

しかし、ノード障害が発生したとき、クラスタウェアが障害を検出し、別の正常ノードでVIPを起動するまでの間、そのVIPがネットワーク上に存在しない時間帯ができます。その間にOracleクライアントがそのVIPに接続リクエストを発行した場合、TCP/IPのレベルで応答を待つという動作になります。

1回の接続リクエストの応答がハングアップすることに対処するため、接続記述子にタイムアウトのパラメータを設定することができます。TRANSPORT_CONNECT_TIMEOUTは1回の接続リクエストのTCP/IPレベルでのタイムアウトです。CONNECT_TIMEOUTはTCP/IPレベルでのタイムアウトを含む、Oracle Netの処理を含めた1回の接続リクエストのタイムアウトです。

7.2 接続リクエストのリトライ

クラスタウェアが管理しているリソースがフェイルオーバーしている最中にOracleクライアントが接続リクエストを発行すると、その接続リクエストは失敗します。接続時フェイルオーバーの接続リクエストの再試行回数と、再試行間隔を制御できます。RETRY_COUNTが再試行回数で、RETRY_DELAYが再試行間隔です。

img-11

RETRY_DELAYはRETRY_COUNTと組み合わせることで機能します。これらの値の積がサービスのフェイルオーバーにかかる時間より短いと、接続リクエストは最終的にエラーとなります。

ここまで説明した接続時フェイルオーバーは、新規の接続リクエストを発行するときに検出された障害に対処するためのものです。考慮すべきパターンがまだあります。それは、Oracleサーバーに障害が発生したとき、確立済みのコネクションがどのように振る舞うかです。次回はOracleサーバーに障害が発生したときの確立済みコネクションの挙動と、トランザクションの自動再実行について解説する予定です。