Application Server は、高可用性データベース (HADB) を使用して持続セッション状態データを保存します。パフォーマンスを最適化するには、Application Server の負荷に応じて HADB を調整します。データの量、トランザクションの頻度、および各トランザクションのサイズが HADB のパフォーマンスに影響を及ぼす場合があります。そのため、Application Server のパフォーマンスにもその影響が及ぶ場合があります。
この節の内容は次のとおりです。
ここでは、HADB データデバイスのサイズの計算方法と、複数のデータデバイスでの個別ディスクの使用について説明します。
HADB データベースを作成するときに、データデバイスの数と、各データデバイスのサイズを指定します。これらのデバイスは、すべてのユーザーデータを格納できる十分な容量にします。さらに、あとの節で説明されている、内部オーバーヘッドに対応するための追加スペースも確保します。
データベースがデバイス空間を使い果たすと、HADB から Application Server にエラーコード 4593 または 4592 が返されます。
これらのエラーメッセージの詳細については、『Sun Java System Application Server Enterprise Edition 8.2 Error Message Reference』を参照してください。
また、HADBによってこれらのメッセージは履歴ファイルにも書き込まれます。この場合、HADB では、データを挿入または更新するクライアント要求はすべてブロックされます。ただし、削除操作は受け付けられます。
HADB では、セッション状態がバイナリデータとして保存されます。セッション状態は直列化され、BLOB (バイナリラージオブジェクト) として保存されます。各 BLOB は、約 7K バイトのチャンクに分割され、各チャンクは、16K バイトのページにデータベース行 (コンテキスト行はタプルまたはレコードと同義) として保存されます。
各行で小さなメモリーオーバーヘッド (約 30 バイト) が生じます。もっともコンパクトな行割り当て (BLOB チャンク) では、1 ページに 2 行が保存されます。内部断片化により、各ページに1 行しか格納されないこともあります。平均では、各ページの 50% にユーザーデータが格納されます。
ノード障害が発生した場合でも利用できるように、HADB では常に、ユーザーデータがレプリケートされます。HADB ノードには、そのノード自体のデータと、ミラーノードからのコピーデータが保存されます。このように、すべてのデータは 2 回保存されます。平均ではノード容量の 50% がユーザーデータで、各ノードはミラーリングされるので、データデバイスの容量は、ユーザーデータの量の 4 倍以上にしてください。
データの再断片化については、HADB では、再断片化操作の実行中に古いバージョンのテーブルと新しいバージョンのテーブルの両方が保持されます。すべてのアプリケーション要求は古いテーブルで実行されますが、同時に新しいテーブルが作成されています。このため、データベースが主に、セッション状態の BLOB データを格納する 1 つの大きなテーブルとして使用される場合は、デバイス空間に必要な容量をさらに 2 倍にします。したがって、稼働中のデータベースにノードを追加し、すべてのノードを使用するためにデータを再断片化する場合は、利用可能なユーザーデータの量の 8 倍の容量が必要になります。
さらに、HADB の内部使用のために予約されているデバイス空間 (LogBufferSize の値の 4 倍) も考慮に入れます。HADB では、このディスク領域は高負荷時のログバッファーの一時的な記憶域として使用されます。
HADB データデバイスのサイズを大きくするには、次のコマンドを使用します。
hadbm set TotalDatadeviceSizePerNode
このコマンドを実行すると、変更を適用するためにすべてのノードが 1 つずつ再起動されます。このコマンドの使用の詳細については、『Sun Java System Application Server Enterprise Edition 8.2 高可用性 (HA) 管理ガイド』の「HADB の設定」を参照してください。
hadbm では、稼働中のデータベースインスタンスにデータデバイスは追加されません。
パフォーマンスを最適にするには、各データデバイスを個別の物理ディスクに割り当てるべきです。これは、複数のデータデバイスを持つノードがある場合、または同じホストに複数のノードがある場合に当てはまります。
異なるノードに属するデバイスは、異なるデバイスに配置します。Red Hat AS 2.1 では、複数のノードに属するデバイスに同じディスクが使用されていると、非同期の入出力を待つために HADB ノードが常に監視されるので、特にこの措置が重要になります。
HADB ノードでは、出力デバイスで通常行われるように、非同期ではなく同期的に情報、警告、およびエラーが履歴ファイルに書き込まれます。そのため、HADB の動作やパフォーマンスが、履歴ファイルへの書き込み時にディスクの待ち時間による影響を受ける可能性があります。この状況が発生した場合は、履歴ファイル内で次のメッセージによって示されます。
BEWARE - last flush/fputs took too long
この問題を回避するには、HADB 実行可能ファイルと履歴ファイルを、データデバイスとは異なる物理ディスクに保存します。
ほかのプロセスと共存する場合は特に、HADB に十分なメモリーを割り当てることが不可欠です。
HADB ノードスーパーバイザープロセス (NSUP) では、最後に監視が実行されてから経過した時間が追跡されます。その時間が、指定された最大値 (デフォルトでは 2500 ミリ秒) を超えると、NSUP によってノードが再起動されます。メモリーの獲得を競い合うほかのプロセスがシステムに存在し、スワッピングや複数のページフォルトが発生した場合に、この状況になる可能性があります。ブロックされたノードが再起動されると、そのノード上のすべてのアクティブトランザクションが中止されます。
Application Server のスループットが低下し、中止またはタイムアウトが要求された場合は、スワッピングが原因ではないことを確認します。Unix システムでスワッピングのアクティビティーを監視するには、次のコマンドを使用します。
vmstat -S
さらに、HADB の履歴ファイルに次のメッセージがないか探します。このメッセージは HADB ノードが再起動されたときに書き込まれ、M は N より大きい値になります。
Process blocked for .M. sec, max block time is .N. sec
中止されたトランザクションの存在は、次のエラーメッセージによって示されます。
HADB00224: Transaction timed out または HADB00208: Transaction aborted.
最適なパフォーマンスを得るには、すべての HADB プロセス (clu_xxx_srv) が物理メモリーに収まるようにします。ページングやスワッピングが起こらないようにしてください。同じことが、使用される共有メモリーセグメントにも当てはまります。
共有メモリーセグメントのいくつかはサイズを設定できます。それらのセグメントが小さすぎると、パフォーマンスが低下し、ユーザートランザクションが遅延したり、さらには中止されたりします。セグメントが大きすぎると、物理メモリーが無駄になります。
次のパラメータを設定できます。
HADB のデータは、ディスク上に割り当てられたデータデバイスに保存されます。データが処理されるには、そのデータが主メモリーにある必要があります。HADB ノードでは、この用途に共有メモリーの一部が割り当てられます。割り当てられたデータベースバッファーが、処理されるデータに比べて小さいと、多くの処理容量がディスク入出力によって浪費されます。書き込み集約型の操作を行う (たとえば、頻繁に更新されるセッション状態がある) システムでは、ディスク入出力に使用される処理容量が多すぎて要求処理が阻害されないように、データベースバッファーを十分な大きさにしてください。
データベースバッファーは、ファイルシステムのキャッシュに似ています。パフォーマンスを向上させるには、ディスク読み取り操作を待つ必要がないように、できるだけ容量の大きいキャッシュを使用します。データベース全体の内容がデータベースバッファーに収まるようにすれば、最高のパフォーマンスが得られます。しかし、ほとんどの場合、これは実現不可能です。クライアントアプリケーションの作業セットがバッファーに収まることを目標にします。
また、ディスク入出力も調べます。HADB で多数のディスク読み取り操作が実行される場合は、データベースのバッファー容量が不足していることになります。データベースバッファーは、ディスクで使用されるブロックサイズと同じ 16K バイトのブロックに分割されます。HADB では、1 回の入出力操作で読み取り用と書き込み用に複数のブロックがスケジュールされます。
ディスクの使用状況を調べるには、hadbm deviceinfo コマンドを使用します。たとえば、hadbm deviceinfo --details というコマンドを実行すると、次のような出力が表示されます。
NodeNo TotalSize FreeSize Usage 0 512 504 1% 1 512 504 1%
出力の各列の表記の意味は次のとおりです。
TotalSize: デバイスのサイズ (M バイト単位)。
FreeSize: 空きサイズ (M バイト単位)。
Usage: 使用率 (%)
リソースの使用率を調べるには、hadbm resourceinfo コマンドを使用します。たとえば、次のコマンドでは、データバッファープールの情報が表示されます。
%hadbm resourceinfo --databuf NodeNo Avail Free Access Misses Copy-on-write 0 32 0 205910260 8342738 400330 1 32 0 218908192 8642222 403466
出力の各列の表記の意味は次のとおりです。
Avail: バッファーのサイズ (M バイト単位)。
Free: 空きサイズ。この出力例は、データのボリュームがバッファーよりも大きいことを示しています。つまり、常にバッファー全体が使用されています。
Access: バッファー内でブロックがアクセスされた回数。
Misses: キャッシュに見つからなかった (ユーザーがディスク読み取りを待たされた) ブロック要求の数。
Copy-on-write: ディスクへの書き込み中にブロックが変更された回数。
システムを適切に調整するには、ミス回数 (それによる読み取り回数) が、書き込み回数に比べてごく少数になるようにします。この例では、ミスの割合が約 4% である (2 億回のアクセスに対して 800 万回のミスがあった) ことが示されています。これらの数値の許容範囲は、クライアントアプリケーションの要件によって異なります。
データベースバッファーのサイズを変更するには、次のコマンドを使用します。
hadbm set DataBufferPoolSize
このコマンドを実行すると、変更を有効にするためにすべてのノードが 1 つずつ再起動されます。このコマンドの使用の詳細については、『Sun Java System Application Server Enterprise Edition 8.2 高可用性 (HA) 管理ガイド』の「HADB の設定」を参照してください。
HADB では、データの挿入、削除、更新、読み取りなど、データベースを変更するすべての操作が、実行前にログに記録されます。それらの操作が記述されたログレコードは、(タプル) ログバッファーと呼ばれる共有メモリー部分に配置されます。HADB では、これらのログを使用して、トランザクションが中止されたときの取り消し操作、ノードクラッシュ時の復元、およびミラーノード間のレプリケーションが行われます。
ログレコードは、ローカルで処理されてミラーノードに送られるまでは、バッファー内に残っています。ログレコードは、トランザクションの結果 (コミットまたは中止) が確定するまで保持されます。HADB ノードでタプルログの残りが少なくなると、ユーザートランザクションが遅延し、場合によってはタイムアウトになります。
デフォルト値から開始します。履歴ファイルで HIGH LOAD 情報メッセージを探します。関連するメッセージには必ず、tuple log または log と、発生した内部リソース競合の説明が含まれます。
通常の操作では、ログ領域の使用率は 70 〜 80% と報告されます。領域再生が「低速」と言われるのはこのためです。HADB では、ノードクラッシュが発生時した場合、復旧するためにできるだけ多くのログデータを必要とします。
ログバッファーのサイズと使用状況に関する情報を表示するには、次のコマンドを使用します。
hadbm resourceinfo --logbuf
たとえば、次のような出力が表示されます。
Node No. Avail Free Size 0 44 42 1 44 42
出力の各列の表記の意味は次のとおりです。
Node No.: ノード番号。
Avail: バッファーのサイズ (M バイト単位)。
Free Size: 空きサイズ (M バイト単位)。データのボリュームがバッファーよりも大きい場合は、常にバッファー全体が使用されます。
ログバッファーのサイズを変更するには、次のコマンドを使用します。
hadbm set LogbufferSize
このコマンドを実行すると、変更を有効にするためにすべてのノードが 1 つずつ再起動されます。このコマンドの使用の詳細については、『Sun Java System Application Server Enterprise Edition 8.2 高可用性 (HA) 管理ガイド』の「HADB の設定」を参照してください。
ノード内部ログ (nilog) には、ローカルノードの物理的 (論理的の反対、行レベル) 操作に関する情報が記録されます。たとえば、ディスクブロックの割り当てと解放、および B ツリーブロックの分割があるかどうかに関する情報が提供されます。このバッファーは、共有メモリーに保持され、定期的にディスク (個別のログデバイス) との照合も行われます。このバッファーのページサイズおよび関連付けられているデータデバイスのサイズは 4096 バイトです。
大きい BLOB には、必然的に多くのディスクブロックが割り当てられるので、ノード内部ログの負荷が大きくなります。nilog の各エントリは小さいため、通常はこれが問題になることはありません。
デフォルト値から開始します。履歴ファイルで HIGH LOAD 情報メッセージを探します。関連するメッセージには、nilog と、発生した内部リソース競合の説明が含まれています。
ノード内部ログバッファーの情報を表示するには、次のコマンドを使用します。
hadbm resourceinfo --nilogbuf
たとえば、次のような出力が表示されることがあります。
Node No. Avail Free Size 0 11 11 1 11 11
nilog バッファーのサイズを変更するには、次のコマンドを使用します。
hadbm set InternalLogbufferSize
hadbm を実行すると、変更を有効にするためにすべてのノードが 1 つずつ再起動されます。このコマンドの使用の詳細については、『Sun Java System Application Server Enterprise Edition 8.2 高可用性 (HA) 管理ガイド』の「HADB の設定」を参照してください。
nilog バッファーのサイズが変更されると、関連付けられているログデバイス (データデバイスと同じディレクトリにある) のサイズも変更されます。内部ログバッファーのサイズは、内部ログデバイスと同じサイズにします。hadbm set InternalLogBufferSize コマンドによって、この要件を確実に満たします。このコマンドを実行すると、ノードが停止され、InternalLogBufferSize の値が増やされ、内部ログデバイスが再初期化され、ノードが再起動されます。この一連の操作は、すべてのノードに対して実行されます。
行レベル操作ごとに、データベースのロックが必要です。ロックは、トランザクションがコミットまたはロールバックされるまで保持されます。ロックは行 (BLOB チャンク) レベルで設定されます。つまり、大きなセッション状態には多数のロックが必要になります。ロックは、主ノードとミラーノードの両方の操作に必要です。したがって、1 回のBLOB 操作で、2 つの HADB ノードに同じ数のロックが割り当てられます。
テーブルの再断片化が実行される場合、HADB には追加のロックリソースが必要です。そのため、通常のユーザートランザクションが獲得できるのは、割り当てられたロックのうち半分だけです。
利用可能なロックオブジェクトが HADB ノードにない場合は、ログファイルにエラーが書き込まれます。詳細については、『Sun Java System Application Server Enterprise Edition 8.2 Error Message Reference』の第 14 章「HADB Error Messages」を参照してください。
必要なロック数を計算するには、次のパラメータを見積もります。
セッションデータを要求して HADB に保存する同時ユーザーの数 (ユーザーあたり 1 セッションレコード)
BLOB セッションの最大サイズ
持続性の範囲 (session または modified-session の場合はセッションデータの最大サイズ、modified-attribute の場合は属性の最大数)。セッションデータが変更されるたびに、setAttribute() を呼び出す必要があります。
次のように仮定します。
x を同時ユーザーの最大数とします。つまり、x 個のセッションデータレコードが HADB に存在するとします。
y をセッションサイズ (session または modified-session の場合) または属性サイズ (modified-attribute の場合) とします。
この場合、HADB に書き込まれるレコード数は次のようになります。
xy/7000 + 2x
挿入、削除、更新、読み取りなどのレコード操作では、1 つのレコードに 1 つのロックが使用されます。
ロックは、主レコードとホットスタンバイレコードの両方で保持されます。したがって、挿入、更新、および削除の操作では、1 回のトランザクションに、レコード数の 2 倍のロック数が必要です。読み取り操作では、主レコードのロックのみが必要です。再断片化と二次インデックスの作成が行われるときには、関係するテーブルのログレコードも、作成されるフラグメントレプリカに送信されます。その場合、1 回のトランザクションに、関係するレコード数の 4 倍のロック数が必要です (すべてのクエリーが、その影響を受けるテーブルに対するものと想定した場合)。
再断片化が実行される場合、設定するロック数は次のようになります。
Nlocks = 4x (y/7000 + 2) = 2xy/3500 + 2x
それ以外の場合、設定するロック数は次のようになります。
Nlocks = 2x (y/7000 + 2) = xy/3500 + 4x
デフォルト値から開始します。Application Server のログファイルで、指示されたエラーコードを持つ例外を探します。再断片化が行われていない通常の操作では、クライアントアプリケーションはロック数の半分しか使用しないこともあります。
割り当てられたロック数と使用中のロック数に関する情報を得るには、次のコマンドを使用します。
hadbm resourceinfo --locks
たとえば、このコマンドを実行したときに、次のような出力が表示されることがあります。
Node No. Avail Free Waits 0 50000 50000 na 1 50000 50000 na
Avail: 利用可能なロックの数。
Free: 使用中のロックの数。
Waits: ロックを待っていたトランザクションの数。すべてのロックが利用可能な場合は「na」 (適用外) が示されます。
ロック数を変更するには、次のコマンドを使用します。
hadbm set NumberOfLocks
hadbm を実行すると、変更を有効にするためにすべてのノードが 1 つずつ再起動されます。このコマンドの使用の詳細については、『Sun Java System Application Server Enterprise Edition 8.2 高可用性 (HA) 管理ガイド』の「HADB の設定」を参照してください。
ここでは、パフォーマンスに影響するいくつかのタイムアウト値について説明します。
これらの値は、サーバーがタイムアウトになるまでにプールからの接続を待機する時間を制御します。ほとんどの場合はデフォルト値で十分です。チューニングの詳細については、「JDBC 接続プールのチューニング」を参照してください。
次に、パフォーマンスに影響する可能性がある値のいくつかを示します。
response-timeout-in-seconds - ロードバランサプラグインが応答を待機する時間。この時間が経過すると、インスタンスのデッド状態が宣言され、クラスタ内の次のインスタンスに処理が継続されます。この値は、最悪 (高負荷) の状況下でのサーバーインスタンスからの要求の最大処理時間に合わせた十分な長さにします。
診断プログラム: interval-in-seconds - インスタンスが正常であるかどうかを確認するためにロードバランサが Ping を実行する頻度を指定します。デフォルト値は 30 秒です。response-timeout-in-seconds が最適に調整されていて、サーバーのトラフィックがそれほど多くない場合は、デフォルト値で十分です。
診断プログラム: timeout-in-seconds - ロードバランサがインスタンスに対して Ping を実行したあとに処理を待つ時間。デフォルト値は 100 秒です。
診断プログラムの interval-in-seconds と timeout-in-seconds の値の組み合わせによって、ロードバランサプラグインからサーバーインスタンスに行く追加トラフィックの量が決まります。
ロードバランサプラグインの設定の詳細については、『Sun Java System Application Server Enterprise Edition 8.2 高可用性 (HA) 管理ガイド』の「ロードバランサの設定」を参照してください。
sql_client タイムアウト値が、パフォーマンスに影響する場合があります。
次に、オペレーティングシステムの構成について説明します。
セマフォーの数が少なすぎると、HADB に障害が発生し、次のエラーメッセージが表示されることがあります。
No space left on device
これは、データベースの起動時または実行中に発生することがあります。セマフォーはオペレーティングシステムによってグローバルリソースとして提供されるので、その構成は、HADB だけでなく、ホストで実行されるすべてのプロセスによって決まります。Solaris では、/etc/system ファイルを編集することによってセマフォーの設定を構成します。
ノード、NNODES (--hosts オプションによって暗黙的に HADB に送信されるノードの数)、ホストあたりの NCONNS 接続 (HADB 構成パラメータの NumberOfSessions、デフォルト値は 100) を実行するには、次のセマフォー設定を使用します。
set semsys:seminfo_semmap = <default=10> + NNODES set semsys:seminfo_semmni = <default=10> + NNODES set semsys:seminfo_semmns = <default=60> + (NNODES * 8) set semsys:seminfo_semmnu = <default=30> + NNODES + NCONNS
1 つのホストで複数のノードを実行する予定の場合は、必ず semmap = NNODES を設定します。設定を調べるには、sysinfo コマンドと sysdef コマンドを使用します。
共有メモリーの最大サイズを、物理 RAM の合計容量に設定します。さらに、プロセスあたりの共有メモリーセグメントの最大数を、HADB プロセスに対応できるように 6 以上に設定します。ホストで実行されるノードの数に基づいて、システム全体の共有メモリー識別子の数を設定します。
Solaris 9 では、カーネルが変更されたため、hmsys:shminfo_shmseg 変数は使用されなくなっています。Solaris 8 では、/etc/system ファイルに次の設定を追加します。
set shmsys:shminfo_shmmax = 0xffffffff set shmsys:shminfo_shmseg = <default=6> set shmsys:shminfo_shmmni = <default=100> + (6 * NNODES)
デフォルト値は Solaris 8 の値です。デフォルト値かどうかに関係なく、以前の変数値に HADB リソース要件を追加します。
これらの設定を変更したら、ホストを再起動してください。
共有メモリーを 512M バイトに増やすには、次のコマンドを実行します。
echo 536870912 > /proc/sys/kernel/shmmax echo 536870912 > /proc/sys/kernel/shmall
shmmax ファイルには 1 つの共有メモリーセグメントの最大サイズが含まれており、shmall には利用可能にする共有メモリーの合計サイズが含まれています。
この値は、デフォルト値を使用する標準的な HADB ノードに十分な大きさです。デフォルト値を変更する場合は、これらの値の変更も検討してください。
変更後の設定を永続的なものにするには、Linux マシンの /etc/rc.local にこれらの行を追加します。RedHat Linux では、カーネルパラメータを設定する sysctl.conf も変更できます。