- PR -

DBのダーティーリードの対策について

投稿者投稿内容
永井和彦
ぬし
会議室デビュー日: 2002/07/03
投稿数: 276
お住まい・勤務地: 東京都
投稿日時: 2004-03-23 12:07
引用:

このようなケースの場合、具体的には実行状況管理用のテーブルを作成します。
それぞれ管理したい区分に関してデータを作成しておいて、例えば短期的バッチであればSELECT FLG ... FOR UPDATE(で、もしFLGの値として1を取得したらAbort)、中長期バッチであれば初期処理としてUPDATE ... SET FLG=1 ...でCOMMITしておいてからバッチの本体のトランザクションを走らせるといったことをします。
#当然、中長期バッチの最後でこのフラグは落します。

この下準備をした状態で、処理Xに短期バッチと同様なSELECT FLG ... FOR UPDATE処理(Abortに関しても同様)をさせれば大丈夫だと思います。



他の方法の方で検討されているようなので、不要かとも思いましたが、説明不足だったので一応自己フォローしておきます。
#混乱させてしまったようですし

まず、処理Yを短期バッチYaと長期バッチYbと区別します。処理XはXのままです。
さらに長期バッチを「前処理(フラグ立て)、本処理、後処理(フラグ落とし)」の3つに分けます。これをそれぞれYb1、Yb2、Yb3とします。

DBのレコードロック機能を用いてYa、Yb1、Yb3、Xの4つはそれぞれ待ち合うことになります。
#Yb1、Yb3は更新処理を行っている。Ya、Xは更新用参照を行っている。

すると、残りで考えられる競合はYb2とYa、もしくはYb2とXの関係になりますが、YaとXは「Yb2が走っている状態ならば常に立てられているフラグ」を検知するとAbortすることになっていますので、Yb2先行の場合は大丈夫です。

逆のYaもしくはXが先行していた場合に関してですが、Yb1とYb2の間にYaもしくはXが割り込む可能性はありませんので、こちらは有り得ません。
#割り込もうとしたYa(もしくはX)はフラグを検知してAbortしてしまうため

……と、以上のようなロジックで大丈夫だ……という話だったのですが……最初から書いておけばよかったですね。お時間を浪費させてしまい申し訳ありませんでした。

あと、全てが「AutoCommit=OFFのトランザクション」であり、「ConnectionClose(もしくはPoolへの返還)時に確実にCommit(もしくはRollback)が行われること」が前提となっています。これに関しても言葉足らずでした。


[ メッセージ編集済み 編集者: 永井和彦 編集日時 2004-03-23 16:05 ]
matu
ベテラン
会議室デビュー日: 2002/09/01
投稿数: 95
お住まい・勤務地: 東京
投稿日時: 2004-03-23 16:02
 こんにちは。

引用:

永井和彦さんの書き込み (2004-03-23 12:07) より:

他の方法の方で検討されているようなので、不要かとも思いましたが、説明不足だったので一応自己フォローしておきます。
#混乱させてしまったようですし
……と、以上のようなロジックで大丈夫だ……という話だったのですが……最初から書いておけばよかったですね。お時間を浪費させてしまい申し訳ありませんでした。



 こちらこそ理解力が足りなくて申し訳ございません。。。
 処理Xも更新用参照を行っているという部分を見落としていた為になかなか理解
できませんでした。お恥ずかしいのですが再度ご説明いただき理解できました。
ありがとうございます 

 ちなみにCMPのEJBはトランザクションの一貫性を保つためにデータベース側の
SERIALIZEやSELECT...FOR UPDATEを利用しているのでしょうか??
 例えばトランザクションをRequiredでejbLoadからejbStore(UPDATE)の間に
他のプロセス(例えばSQLPlus等)でコミットをかけた場合はどうなるのでしょう?

 もしご存知でしたらご教授ください。

[ メッセージ編集済み 編集者: matu 編集日時 2004-03-23 16:02 ]

スキルアップ/キャリアアップ(JOB@IT)