検索
連載

EJBはトランザクションのやり方次第で速くなるのに…WebSphereサーバ・チューニング入門(6)(1/4 ページ)

PC用表示 関連情報
Share
Tweet
LINE
Hatena

本連載は、Javaアプリケーション・サーバの1つである、IBM WebSphere Application Server(以下、WAS)についてのパフォーマンス・チューニングに関する入門記事です。チューニングといっても、実施するエンジニアによって、その方法は異なりますが、本連載はWASを前提とし、かつ80%のケースをカバーすることを目標とします(編集部注:WASのインストールから学びたい読者は、「バージョン別セットアップマニュアル一覧」のWebSphere Application Serverを参照してください)


トランザクションの仕方を見極めてEJBを速くしよう!

 前回の記事(「あなたのEJBシステム遅くないですか?」)では、EJBシステムの高速化チューニングとして、WASサーバ自体に対して実施するEJBパフォーマンス・チューニング設定を解説しました。前回で解説した内容は、WASの管理コンソールから設定することにより高速化を実現するものでした。

編集部注EJBについて詳しく知りたい読者は、@IT Java Solutuionのカテゴリ「EJB/仮想化/分散技術」をご参照ください。

 今回は、システムごとのEJBのDBトランザクションのやり方を見極めて、EARファイルに含まれるデプロイメント・ディスクリプタ配置記述子)に対してさまざまなパラメータ設定を行います。WASで設定を行う場合を例にとって説明していきますので、WebSphere Application Server Toolkit (以下、AST)あるいは、Rational Application Developer(以下、RAD)という2つのツールを使用します。

 EJBのデプロイメント・ディスクリプタに設定できる項目のうち、以下に列挙する8つの機能について順番に解説を行います(下記リストはインデックスになっています)。

  1. アクセス・インテント(Entity BeanのDBアクセスに対する最適化)
  2. Lifetime in Cache(データ・キャッシュ)
  3. Entity Beanキャッシュ(コミット・オプション)
  4. Read-only Entity Bean(読み取り専用Entity Bean)
  5. Partial Column Update(部分オペレーション)
  6. CMP CMR Read-ahead hints(先行読み取りヒント)
  7. Read-read整合性チェック(キャッシュ・データの検証)
  8. Lightweight Entity Bean(単純なローカルモード、Entity Beanの性能向上の仕組み)

【1】アクセス・インテント(DBアクセスに対する最適化)

 WASは、「アクセス・インテント」と呼ばれるEntity BeanDBアクセスに対する最適化の仕組みを提供しています。「アクセス・インテント」ポリシーを設定することにより、CMP(Container Managed Persistence) Bean(Container Managed Persistence) BeanのDBアクセスの分離レベルを指定します。WASは、7つの「アクセス・インテント」ポリシーをサポートしていて(後述)、「アクセス・インテント」ポリシーは、以下の3つの要素から成り立っています。

  1. Concurrency Control(DBロック解決案)
  2. トランザクション分離レベル
  3. アクセス・タイプ(Read処理かUpdate処理の2つ)

Concurrency Control(Locking Strategy、DBロック解決案)とは?

 Concurrency Control(Locking Strategy)PessimisticあるいはOptimisticの2つに大別されます。

悲観的なDBロック解決案

 「Pessimistic Locking Strategy」は、トランザクション処理の最初でロックを獲得し、トランザクションがコミットあるいはロールバックされるまでロックを保持します。ほかのトランザクションからこのデータへのアクセスは、ロックが解放されるまで待たされます。

図1 「Pessimistic Locking Strategy」のシナリオ例
図1 「Pessimistic Locking Strategy」のシナリオ例

 図1の例では、まず、トランザクション1が残高(1万円)をDBから読み込みます。トランザクション2が同じ口座から残高を読み取ろうとした際に、トランザクション1がロックを解放するまで待たされます。その間にトランザクション1は、残高に2万円の入金処理を行い、コミット処理をします(この時点で、残高は3万円に更新)。

 その後で、トランザクション2の処理が続行されます。その時点で、トランザクション2が読み込んだ残高は3万円となっており、入金処理(1万円)の後にコミットをします。トランザクション2のコミット処理後の残高は、4万円となります。

楽観的なDBロック解決案

 「Optimistic Locking Strategy」は、ほかのトランザクションがリソースへアクセスできない時間を短縮するためのアイデアです。「ロング・ランニング・トランザクション」下で、「長時間にわたり、ほかのトランザクションがリソースにアクセスできない」というシナリオに対する解決案といえます。

 「Optimistic Locking Strategy」では、DB読み取り処理の直前にロックを獲得し、オペレーション終了後、直ちにロックを解放します。Updateロックは、DB更新処理の直前に獲得され、トランザクション終了まで保持されます。

図2 「Optimistic Locking Strategy」のシナリオ例
図2 「Optimistic Locking Strategy」のシナリオ例

 図2では、まず、トランザクション1がデータ(残高)を読み込み、入金処理を行います(コミット処理はまだ実施せず)。その直後に、トランザクション2が同じデータ(残高)を読み込み、入金処理を行います(コミット処理はまだ実施せず)。

 続いて、トランザクション1がデータの更新の有無をチェックし、データ更新がされていないことを確認し、データ更新およびトランザクション・コミットを実施します(残高が3万円に更新される)。

 トランザクション2は、トランザクション1がデータ更新およびコミット処理を実施した後に、データ更新の有無を確認し、データ更新に気付いたため、トランザクションを中止し、トランザクションをやり直します。

 「Optimistic Locking Strategy」は、「Pessimistic Locking Strategy」と比べ、データに対する同時アクセスが寛容です。ただし、ほかのトランザクションによる同一データに対する更新が頻繁に発生する場合には、「Pessimistic Locking Strategy」の採用により、効果が見られるケースがあります。

トランザクション分離レベルの設定で左右されるDBアクセスのパフォーマンス

 トランザクションの4つの分離レベル(「Serializable」「Repeatable Read」「Read Committed」「Read Uncommitted」)は、パフォーマンス性能に影響を与えます。分離レベルの高い設定は、行ロックを増加し、DBへの同時アクセスを減らすため、パフォーマンスが低下します。

 複数トランザクション同時実行時の問題として、「Dirty Read」「Non-repeatable Read」「Phantom Read」の3つがあります。それらについて説明をした後、分離レベルについて説明を行います。

複数トランザクション同時実行時の3つの問題

  • Dirty Read」問題
    トランザクション2が更新/挿入した、コミットされていないデータをトランザクション1が読み込んでしまう
図3 「Dirty Read」問題の例
図3 「Dirty Read」問題の例
  • Non-repeatable Read」問題
    トランザクション1が、トランザクション実行中に2度同じデータを読み込む場合に、1度目と2度目の読み込みの間に、トランザクション2がそのデータの更新を行いコミットすると、読み取りタイミングによってデータの値が異なる場合がある
図4 「Non-repeatable Read」問題の例
図4 「Non-repeatable Read」問題の例
  • Phantom Read」問題
    トランザクション1が、トランザクション実行中に2度同じデータを読み込む場合に、1度目と2度目の読み込みの間に、トランザクション2がデータを挿入すると、読み取りのタイミングによって結果が異なる場合がある
図5 「Phantom Read」問題の例
図5 「Phantom Read」問題の例

4つのトランザクション分離レベルと問題点の関連

 トランザクション分離レベルは、これらの問題に関連しています。表1は、トランザクション分離レベルと上記問題との関連をまとめたものです。

分離レベル Dirty Read Non-repeatable Read Phantom Read
TRANSACTION_SERIALIZABLE 発生しない 発生しない 発生しない
TRANSACTION_REPEATABLE_READ 発生しない 発生しない 発生する
TRANSACTION_READ_COMMITTED 発生しない 発生する 発生する
TRANSACTION_READ_UNCOMMITED 発生する 発生する 発生する
表1 トランザクション分離レベル

 以下に、各トランザクション分離レベルについて簡単に説明します。

  • TRANSACTION_READ_UNCOMMITED
    トランザクション2がレコードを更新すると、その時点(トランザクション2がコミットする前)でトランザクション1から更新した内容が見える(「Dirty Read」)。つまり、トランザクション1と2は、分離されていない
  • TRANSACTION_READ_COMMITTED
    トランザクション2がレコードを更新すると、その更新結果は、トランザクション2がコミットするまでは、トランザクション1には見えない
  • TRANSACTION_REPEATABLE_READ
    トランザクション1がSELECT文を複数回実行した場合に、トランザクション2が更新した内容が、トランザクション1の検索結果に影響を与えることがある(「Non-repeatable Read」)。これを防ぐためには、「TRANSACTION_REPEATABLE_READ」あるいは、「TRANSACTION_SERIALIZABLE」を設定する必要がある
  • TRANSACTION_SERIALIZABLE
    トランザクション1でSELECT文を複数回実行した場合に、トランザクション2が追加(あるいは、削除)した内容がトランザクション1の検索結果に表れる(消える)ことがある(「Phantom Read」)。これを防ぐためには、「TRANSACTION_SERIALIZABLE」を指定する必要がある

コラム 「DB2のトランザクション分離レベル」

DB2が定義するトランザクション分離レベルは、上述したEJB(JDBC)のトランザクション分離レベルと多少異なります。以下にそれらをまとめます。

EJB(JDBC) DB2
TRANSACTION_SERIALIZABLE Repeatable Read(RR)
TRANSACTION_REPEATABLE_READ Read Stability(RS)
TRANSACTION_READ_COMMITTED Cursor Stability(CS)
TRANSACTION_READ_UNCOMMITED Uncommitted Read(UR)
表2 DB2のトランザクション分離レベルとJDBCのトランザクション分離レベル

Copyright © ITmedia, Inc. All Rights Reserved.

       | 次のページへ
ページトップに戻る