矢木 覚 (新日鉄ソリューションズ株式会社)
インターネット上でB to B、B to Cの大規模なサービスが提供され、多くの利用者を集めています。そのため、こうしたサービスのシステムダウンによる企業への影響も、非常に大きなものとなっています。ビジネスチャンス・売り上げのロストはもちろん、場合によっては企業への信頼低下につながるかもしれません。
そのため、システムの基盤を構築する上で、高可用性(High Availability)を検討することは非常に重要です。高可用性の実現には、システム構成を冗長化し、SPOF(Single Points Of Failure: 単一障害点)を解消する必要があります。
一般的にデータベースを用いたシステムでは、SPOFの解消をシステム構成の二重化(クラスタ)で実現します。図1の例では、全く同一のハードウェアをActive/Standby構成で用意し、クラスタソフトによりアプリケーション・ハードウェアを監視しています。障害発生時には待機系のサーバに切り替え、障害発生によるダウンタイムを減少させます。
図1 Active/Standby構成としたOracle Database (通常運用時)
図2 Active/Standby構成としたOracle Database (障害発生時)
Active/Standby構成によるクラスタでは、SPOFを解消し、可用性を向上させることができますが、以下のような課題も存在します。
待機系サーバの調達コスト・ランニングコストが高価 通常、待機系サーバには稼動系サーバと同様のハードウェアを用います。しかし、Active/Standbyという名のとおり、平常時のStandby機は起動しているだけで、計算機リソース(CPU・メモリ)が有効活用されません。
大規模構成になるに伴い、クラスタ切り替えによるダウンタイムが増大 稼動系ノードで障害が発生した場合には、クラスタソフトウェアや構成により挙動は若干異なるものの、大きく分類して以下の処理が実施されます。
(a) 稼動系のノードダウン(あるいは、プロセスダウン、NIC障害検知)検出
(b) ボリュームマネージャアクセス権移動
(c) ファイルシステムマウント
(d) Oracle Databaseインスタンス起動
(e) インスタンスリカバリの実施
これらの課題を、Active/Active 型クラスタ構成の採用により解決した製品が、Oracle RACです。クラスタデータベースシステムとして、Oracle RACには以下の特徴があります。
Active/Active 型クラスタによる、計算機リソースの有効利用
障害発生時の、高速なリカバリ処理
計算機リソース不足時の、リソース(ノード)の追加によるスケールアウト
図3 Oracle RACの構成
ここで重要な点は、Oracle RACはActive/Active型かつ共有データベース(シェアードエブリシング)型のクラスタ構成であるということです。これは、複数インスタンスからの共有データベースへの同時更新を、高速に処理しなければならないことを意味します。そして、これを実現する機能がCache Fusionなのです。 次章では、Oracle RACの前身であるOracle Parallel Server (OPS)時代から、Cache Fusion実装へ至るクラスタデータベースの進化について紹介します。
Oracle RACの前身であるOPSは、複数のOracleインスタンスから単一のデータベースへの同時操作を可能にしました。OPSのアーキテクチャ上の特徴は以下のとおりです。
ノード間でメモリは非共有・ディスクは共有
1つのデータベースに対して、Oracleインスタンスは各ノードで稼働
全てのインスタンスでデータファイルと制御ファイルを共有(各インスタンスは専用のREDOログを持ちます)
データブロックの一貫性をParallel Cache Managementロック(PCMロック)を用いて担保
図4 OPSの構成
OPSでは分散ロックマネージャ(DLM)を用い、複数ノードからの共有データベースへの同時更新を制御しています。その際に、ノード間でデータブロックの一貫性を担保する仕組みがParallel Cache Managementロック(PCMロック) です。
PCMロックには大きく分類すると三つのモードがあります。
共有(Share)
: DBブロックの読み込み用に共有可能なロック。参照時に取得されます。
排他(Exclusive)
: 他インスタンスとは共有不可能なロック。更新時に取得されます。
開放(Null)
: どのインスタンスもPCMロックを保有していません。
また、ノード間でのデータブロック競合が起こる状況は、以下の四つに分類できます。
read/read
: 読み取り中のリクエストに対する別ノードからの読み取りリクエスト
read/write
: 読み取り中のリクエストに対する別ノードからの書き込みリクエスト
write/read
: 更新中のブロックに対する別ノードからの読み込みリクエスト
write/write
: 更新中のブロックに対する別ノードからの更新リクエスト
read/readの場合にはPCMロックの競合は発生しませんが、その他の競合状況では、PCMのロック変換処理と共有ディスクを介してのデータブロックのノード間受け渡しが必要となります。
このデータブロックの受け渡し処理をPINGと呼びますが、DISK I/Oを伴うPING処理の発生を、アプリケーションやデータベースの物理設計の工夫によっていかに抑えるかという点が、OPSを扱う上で非常に重要でした。
Oracle7 Parallel Serverでは、PCMロックの割り当て方式としてhashed lock方式を利用していました。このロック方式は1つのロックで複数ブロックをロックしてしまうため、PCMロック変換およびPING発生という面で効率が悪いものでした。 Release 7.3ではFine Grain Locking(DBAロック)という、ロック1つでデータブロック1つをロックできる方式が使用可能になったため、主に参照系のデータウェアハウス処理でOPSが使用されるようになりました。
(注:Fine Grain LockingはRealse7.3においてはハードウェア・OSによって使用可否がありましたが、Oracle8 Parallel Serverで 全プラットフォーム共通の機能として実装されました。)
Oracle8i Parallel Server では(write/read) 競合発生時のみ、Disk経由のPING処理ではなく、インターコネクトでの高速ブロック転送(Cache Fusion) が可能になりました。 このCache Fusionテクノロジーにより、OPSはトランザクションモデル(ulTP系) への適用が可能となりました。
このように、PCMロックの変換、それに伴うDISK経由でのデータブロック受け渡し(PING)を抑制するため、OPSを扱う技術者には経験・スキルが求められました。例えば、各ノードがアクセスするデータ領域を分割し、書き込みやデータローディングを制御する。競合発生抑制の為のパラメタ設定やエクステントの事前割り当てといった工夫が必要でした。
Oracle9i RAC では Full Cache Fusionが実装されました。すなわち、(write/write)を含む全てのパターンでインターコネクト回線を用いた高速ブロック転送が行われるようになったのです。これにより、Oracle RACは性能面でもスケールアウトするようになり、ほぼ全ての業種・業務において、特段の工夫なく適用可能になりました。
なお、これまでPCMロックと呼んできたロック方式は、Oracle9i RAC以降GCSロックと呼ばれるようになりました。また、分散ロックマネージャ(DLM)についても同様に、Global Resource Directory(GRD)として扱われるようになりました。
本章では、データブロックの動きやロックの変化など、Cache Fusionが行われる様子を実例を交えて解説します。はじめにCache Fusionの基本的な動作について説明しておきましょう(図5)。 GRDで管理されている各データブロックには、「マスターノード」が存在します。このマスターノードにGCSロックの付与あるいはブロック転送を依頼することにより、Cache Fusionを行います。すなわちCache Fusionは、基本的には3ノードのメッセージ交換により処理が完結するのです。
図5 Cache Fusionの基本的な動作
続いて、以降の解説で利用するサンプルテーブルやスクリプトを紹介します。
まず、実例で使用するサンプルテーブルは以下のとおりです。
employee表 (DBA_OBJECTS表のOBJECT_IDは70306)
| A | NUMBER |
| B | VARCHAR2 (30) |
バッファキャッシュ上のGCSロックホルダー状態を確認したSQL文は以下のとおりです。以降、【V$BH 確認SQL】と記載します。
select o.object_name, b.status , file# , block#
from v$bh b , dba_objects o
where o.data_object_id = b.objd
and o.object_name = 'EMPLOYEE'
and b.status != 'free'
and b.class# = 1
SQL実行中の待機イベントの様子は、event 10046というSQLトレースの拡張機能を用いて取得しています。
alter session set events '10046 trace name context forever, level 8';
また、環境はローカル管理表領域、手動セグメント管理(フリーリスト管理)の表領域上に構築されています。Oracle Databaseのバージョンは10gR2での2ノードRAC、プラットフォームはIA Linux x86 です。
※ 以降の図示による解説では3ノード以上のRAC環境を想定していますが、実例は2ノードRACによる確認結果となります。
図6 Cache Fusionの動作(read/read)
Step1 :
Node2上でSCOTTユーザのEmployee表が検索(SELECT)されています。
Step2 :
Node1はマスターノードであるNode3に対して、共有モード(Share)でのリクエストを出します。
Step3 :
マスターノードであるNode3は、Node2がブロックを保持していることを認識しているため、インターコネクト経由でのPINGメッセージをNode2に送り、ロックの許可を行います。
Step4 :
Node2は、インターコネクト経由でブロックをNode1に送ります。
実環境で動作確認
初期状態
node2にて以下SQLを発行します。
SQL> select * from employee;
node1のV$BH確認SQL発行結果
no rows selected
node2のV$BH確認SQL発行結果
| OBJECT_NAME | STATUS | FILE# | BLOCK# | |||
| ------------------------------ | -------------- | ---------- | ---------- | |||
| EMPLOYEE | scur | 1 | 37842 |
ここで、node2においてSTATUS = SCUR となっているため、CURRENTブロックを共有モードで保持していることを示しています。
node1 にて以下SQLを発行します。
SQL> select * from employee;
その結果、バッファキャッシュ上のGCSロックの状態は以下のように変化しました。
node1のV$BH確認SQL発行結果
| OBJECT_NAME | STATUS | FILE# | BLOCK# | |||
| ------------------------------ | -------------- | ---------- | ---------- | |||
| EMPLOYEE | scur | 1 | 37842 |
node2のV$BH確認SQL発行結果
| OBJECT_NAME | STATUS | FILE# | BLOCK# | |||
| ------------------------------ | -------------- | ---------- | ---------- | |||
| EMPLOYEE | scur | 1 | 37842 |
node1、node2ともにSTATUS = SCURの状態でデータブロックを保持していることが確認できます。
次に、node1 にてSQL文(select文) を発行した際のSQLトレース(event10046)結果を確認しますと、以下が確認されました。
OBJECT_ID = 70306 ブロック# =37842のデータブロックがCache Fusionにより転送されていることが確認されます。図7 Cache Fusionの動作(read/write)
Step1 :
Node2上でSCOTTユーザのEmployee表が検索(SELECT)されています。
Step2 :
Node1はマスターノードであるNode3に対して、排他モード(Exclusive)でのリクエストを出します。
Step3 :
マスターノードであるNode3は、Node2がブロックを保持していることを認識しているため、インターコネクト経由でのPINGメッセージをNode2に送り、ロックの許可を行います。
Step4 :
Node2は自分のロック(共有モード)をクローズし、インターコネクト経由でブロックをNode1に送ります。 このとき、Node2のブロックはCRブロック(Consistent Read)となります。今後はCR要求を受けた際に使用されます。
実環境で動作確認
初期状態
node2にて以下SQLを発行します。
SQL> select * from employee;
node1のV$BH確認SQL発行結果
no rows selected
node2のV$BH確認SQL発行結果
| OBJECT_NAME | STATUS | FILE# | BLOCK# | |||
| ------------------------------ | -------------- | ---------- | ---------- | |||
| EMPLOYEE | scur | 1 | 37842 |
ここで、node2においてSTATUS = SCUR となっているため、CURRENTブロックを共有モードで保持していることを示しています。
node1 にて以下SQLを発行します。
SQL> update employee set b='node1' where a=1;
その結果、バッファキャッシュ上のGCSロックの状態は以下のように変化しました。
node1のV$BH確認SQL発行結果
node2のV$BH確認SQL発行結果 node2がSCUR でもっていたデータブロックはCRブロックとなり、 node1にてXCURブロックとして、すなわちCURRENTブロックが排他モードで取得されていることが確認できます。次に、node1 にてSQL文(update文) を発行した際のSQLトレース(event10046)結果を確認しますと、以下が確認されました。
OBJECT_ID = 70306 ブロック# =37842のデータブロックがCache Fusionにより転送されていることが確認されます。図8 Cache Fusionの動作(write/read)
Step1 :
Node2上でSCOTTユーザのEmployee表が更新(UPDATE)されています。
Step2 :
Node1上で、SCOTTユーザのEmployee表を検索(SELECT)します。 このときに、読み込み要求は一貫性読み込みのため、CR要求となります。
Step3 :
マスターノードであるNode3は、Node2がブロックのコピーを獲得し、ロールバックしなくてはならないことを伝えます。
Step4 :
Node2は現行ブロックにUNDOセグメントを適用し、CRブロックを生成します。
Step5 :
CRブロックが転送されます。
実環境で動作確認
初期状態
node2にて以下SQLを発行します。
SQL> update employee set b='node2' where a=2;
node1のV$BH確認SQL発行結果
no rows selected
node2のV$BH確認SQL発行結果
ここで、node2においてSTATUS = XCUR となっているため、CURRENTブロックを排他モードで保持していることを示しています。
node1 にて以下SQLを発行します。
SQL> select * from employee;
その結果、バッファキャッシュ上のGCSロック状態は以下のように変化しました。
node1のV$BH確認SQL発行結果
node2のV$BH確認SQL発行結果
node2にてCRブロックが作成され、node1に転送されていることが確認できます。
次に、node1 にてSQL文(select文) を発行した際のSQLトレース(event10046)結果を確認しますと、以下が確認されました。
OBJECT_ID = 70306、ブロック# =37842 のデータブロックがCache FusionによりCRブロックとして転送されていることが確認されます。
図9 Cache Fusionの動作(write/read)
Step1 :
Node2上でSCOTTユーザのEmployee表が更新(UPDATE)されています。
Step2 :
Node1はマスターノードであるNode3に対して、排他モード(Exclusive)でのリクエストを出します。
Step3 :
マスターノードであるNode3は、Node2がブロックを保持していることを認識しているため、インターコネクト経由でのPINGメッセージをNode2に送り、ロックの許可を行います。
Step4 :
Node2は、ブロックを保持したまま、インターコネクト経由で変更済みブロック(ダーティーブロック)をNode1に送ります。 この際に、Node2の持つブロックはパストイメージ(PI)となり、PIは障害回復からのリカバリにおいて使用されます。
実環境で動作確認
初期状態
node2にて以下SQLを発行します。
SQL> update employee set b='node2' where a=2;
node1のV$BH確認SQL発行結果
no rows selected
node2のV$BH確認SQL発行結果
ここで、node2においてSTATUS = XCUR となっているため、CURRENTブロックを排他モードで保持していることを示しています。
node1 にて以下SQLを発行します。
SQL> update employee set b='node1' where a=1;
その結果、バッファキャッシュ上のGCSロック状態は以下のように変化しました。
node1のV$BH確認SQL発行結果
node2のV$BH確認SQL発行結果
node1にXCURモードでデータブロックが保持され、もともと保持していたnode2のデータブロックはPI(パストイメージ)に変更されたことが確認されます。
次に、node1 にてSQL文(update文) を発行した際のSQLトレース(event10046)結果を確認しますと、以下が確認されました。
OBJECT_ID = 70306 ブロック# =37842のデータブロックがCache Fusionにより転送されていることが確認されます。このように、Full Cache Fusionテクノロジーにより全てのケースにおいてインターコネクトを利用した高速ブロック転送が行われ、Oracle RACは高いスケーラビリティと、アプリケーションからの透過性というメリットを得られたのです。
最後に、Oracle RAC環境でパフォーマンスを監視する際のポイントについてご紹介します。 Oracle RAC環境においても、パフォーマンス管理始めの一歩 で紹介されているstatspackツールにより、環境ごとのインスタンス効率、load profileや待機イベントの様子から、データベースの状態監視やボトルネックの検出が可能です。
ただし、RACの場合には「Cache Fusion」の項に記載しているとおり、シングルデータベースとは異なるクラスタ固有の処理が行われています。Full Cache Fusionにより、クラスタ固有の処理負荷は大きく軽減されましたが、同一ブロックに対する各ノードからの同時アクセスによる競合(例えばインデックスのリーフブロックに対するアクセス競合など) によってCache Fusionが多発し、処理遅延が発生することもあり得ます。
こういったボトルネックが、statspackの取得間隔(例えば30分おき)の間に恒久的に発生している場合はstatspackレポートによる解析が可能ですが、ある一瞬の間のボトルネックであった場合には、一瞬の処理遅延あるいは待機が大きかったとしても、全体(取得間隔の30分)から見ると均一化されてしまうため、statspackレポートからの解析を行うことは困難となります。
そこで、瞬間的な処理遅延・待機を確認するために、DBAはV$SESSION表およびV$SESSION_WAIT表の情報を定期的 (例えば5秒間隔など)に取得する必要があります。また、取得した情報を解析する際にも考慮が必要です。Oracle Database 10g以降では、バックグラウンドプロセスMMONとMMNLがアクティブセッションの待機イベントを常に記録します。Enterprise Edition + Diagnostic Packを用い、Automatic Workload Repository(AWR)とActive Session History(ASH)を使用することによって、V$ACTIVE_SESSION_HISTORYやDBA_HIST_ACTIVE_SESS_HISTORYから待機イベントの履歴を確認できるようになりました。また、ASHレポート($ORACLE_HOME/rdbms/admin/ashrpt.sql)や、Enterprise Managerを用いることにより、視覚的に待機の状態を確認することも可能になりました。
図10 Oracle Enterprise Managerから待機イベントクラス「Cluster」で遅延が発生していることを確認
これらのツールを有効に用いることが、ワークロードの管理をするうえでたいへん重要です。
Copyright © 2008, Oracle Corporation Japan. All rights reserved.
無断転載を禁ず
この文書はあくまでも参考資料であり、掲載されている情報は予告なしに変更されることがあります。日本オラクル社は本書の内容に関していかなる保証もいたしません。また、本書の内容に関連したいかなる損害についても責任を負いかねます。
Oracleは米国Oracle Corporationの登録商標です。文中に参照されている各製品名及びサービス名は米国Oracle
Corporationの商標または登録商標です。その他の製品名及びサービス名はそれぞれの所有者の商標または登録商標の可能性があります。
矢木 覚(やぎ さとる)
Oracle Database と Real Application Clusters をこよなく愛するエンジニア。 男は黙ってSQL*Plus タイプのDBA1.0 だったが、最近になって、Enterprise Managerを駆使することも重要だと気づきはじめる。 日々、Oracleを楽しみながら奮闘中!