連載
» 2004年10月06日 00時00分 公開

RDBMSアーキテクチャの深層(4):OracleとDB2、ロッキング・メカニズムはこれだけ違う (1/2)

本連載はOracleを使ったデータベースシステムの開発・運用管理にある程度の知識を持つ読者を対象に、Oracle以外の商用RDBMSであるMicrosoft SQL ServerとIBM DB2とのアーキテクチャの違いを明らかにし、マルチベンダに対応できるデータベースシステムの設計・開発・運用ノウハウを紹介していく。(編集局)

[阿尾操, 安間裕,アクセンチュア・テクノロジー・ソリューションズ]

はじめに

主な内容

--Page 1--

はじめに

今回扱うRDBMSとその対象内容

分離レベル

--Page 2--

ロックの制御

ロック待機への対処

ロック・エスカレーション

今回のまとめ


 本連載の第2回「OracleとDB2、アーキテクチャはこれだけ違う」において、OracleとDB2のアーキテクチャの違いについて解説しました。同じRDBMSでも、アーキテクチャは随分と異なることが理解できたと思います。当然ながら、アーキテクチャが異なれば、RDBMSを利用するアプリケーションの振る舞いも異なります。今回は、その中でも、Oracle経験者がDB2を扱った場合に、最も戸惑うと思われる「分離レベルとロッキング・メカニズム」を取り上げます。

 なお、以降の説明では、特に断りのない限り、「Oracle」はOracle9i Enterprise Edition、および「DB2」はDB2 Universal Database V8.1 Enterprise Server Editionの各製品に関する説明とします。

今回扱うRDBMSとその対象内容

 今回は、すでにOracleでのアプリケーション開発経験があり、今後、DB2の導入を検討しているアプリケーション開発者向けに、「分離レベルとロッキング・メカニズム」の観点から、アプリケーション並行性の改善に役立つ内容を解説します(図1)。

図1 今回扱うRDBMSとその対象内容 図1 今回扱うRDBMSとその対象内容

分離レベル

 DB2は、ANSI/ISO標準のトランザクション分離レベルをすべてサポートしています。それに対し、Oracleは、Read Committed、Serializableの2つをサポートしています(表1)。OracleもDB2もデフォルトのトランザクション分離レベルはRead Committedです。Read Committedとは、コミットされたデータのみ参照が許されることでデータの一貫性を保証するものです。まず、OracleとDB2のデフォルト分離レベルであるRead Committedについて、両者の振る舞いの違いを見ていきます。

ANSI/ISO標準トランザクション分離レベル Oracle DB2
Uncommitted Read(未コミット読み取り) 未サポート
Read Committed(コミット読み取り)
(デフォルト)

(デフォルト)
Repeatable Read(繰り返し可能読み取り) 未サポート
Serializable(直列可能)
表1 OracleとDB2がサポートする分離レベルの違い

 OracleとDB2では、このトランザクション制御の実装の仕方が異なるため、同じRead Committedであっても、トランザクションの振る舞いが異なります。

 最も大きな違いは、更新中のデータに対して検索を行った場合です。DB2では、検索時に共有ロックをかけます。しかし、読み取るデータが更新中の場合は、すでにそのデータに排他ロックがかかっているため、共有ロックをかけることができません。つまり、DB2では更新中のデータに読み手はアクセスできず、検索処理が待たされます。一方、Oracleでは、マルチ・バージョン一貫性制御により、UNDO表領域に保持された更新前の情報を読み込むため、読み取るデータが更新中であっても検索処理が待たされることはありません。この両者の癖を理解していないと、アプリケーション開発者は、パフォーマンス劣化やデッド・ロックなどのトラブルに見舞われることになります(図2)。

図2 更新中のデータに対して検索を行った場合のOracleとDB2の比較 図2 更新中のデータに対して検索を行った場合のOracleとDB2の比較

 DB2において、更新中のデータが確定されるまで検索処理が待たされる振る舞いは、複数アプリケーション間の同時実行性を損ないます。これに対しては、「未コミット読み取り」という、ダーティー・リードを許す方法がありますが、実用的なアプリケーションで適用できるケースはごくまれであるため、ここでは取り上げません。

 ここでは、いかにしてダーティー・リードを使わずにDB2で優れた同時実行性を実現すればよいかを考えます。ポイントはロック取得時間(ほかのトランザクションからの更新を許さない時間)を短くするような排他制御のアプリケーション設計を行うことです。ロック取得時間が短ければ、検索処理と重複する機会を減らすことができます。これには、オプティミスティック・ロック(楽観的ロック)と呼ばれる実装方法をよく用います。オプティミスティック・ロックのフローは以下のようになります。

クライアントサーバシステムのプログラミング例

  1. ロックを取得せずにデータを読み込む。
  2. 読み込んだデータをアプリケーション上(画面上)で変更する。
  3. UPDATE実行のタイミングで、ロックをかけて再度データを読み込む。
  4. データベース上でデータ変更の有無を列データの更新時間などを利用して確認する。
  5. ほかのユーザーによってデータが変更されていなければ、コミット処理を行い、更新を確定する。
    もし、ほかのユーザーによってデータが変更されていれば、ロールバック処理を行う。アプリケーション上での変更データは破棄して、ユーザーに再入力を促す。

 ただし、オプティミスティック・ロックは、頻繁に複数ユーザーが同時に同一データを変更するようなシステムだと、更新に失敗し、ユーザーに再入力を促す確率が高くなるため、利便性が低くなる場合があります。そういった場合においては、1回目の読み込み時(上記(1)のタイミング)でロックをかける設計も検討するべきでしょう。また加えて、データにロックをかけて画面表示するような場合は、画面を表示したまま放置することがないよう、一定時間内に画面上から入力がなければ、取り込んだデータを自動的に破棄するようなアプリケーションの設計にする必要があります。

 つまり、DB2の場合、オプティミスティック・ロックによる実装が並行性の改善には有効ですが、オプティミスティック・ロックによる画一的な設計でよいというわけではありません。アプリケーションの要件、ユーザーの利便性を満たす排他制御方法を選択する必要があります。(次ページに続く)

Point

  • OracleもDB2もデフォルト分離レベルは、コミットされたデータのみを取得するRead Committedであるが、その振る舞いが異なる。DB2では更新中のデータに読み手はアクセスできずに検索処理が待たされる。一方、Oracleでは、マルチ・バージョン一貫性制御により、UNDO表領域に保持された更新前の情報を読み込むため、読み取るデータが更新中であっても検索処理で待たされることはない。
  • DB2では、ロック取得時間(ほかのトランザクションからの更新を許さない時間)を短くし、検索処理と重複する機会を減らすために、オプティミスティック・ロック(楽観的ロック)の導入を検討する。

       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。