DBのデータを更新するポリシーには主に以下の三つがある。
これらはあくまでポリシーであって正しい、間違いといった概念ではない。
どういった内容か見ていこう。
後勝ちとは更新の上書きを防止しない方法だ。たとえばマスタ等は、常にユーザが正しい更新をするという前提で設計をする。
UPDATE TABLEXXX SET A=1, B=1 WHERE KEY=1 Aさん
UPDATE TABLEXXX SET A=2, B=2 WHERE KEY=1 Bさん
結果 A=2, B=2
2者が同時に開いてAという更新とBという更新をした場合結果的にBだけが残ることになる。
他には更新カラムを動的に変更し、ユーザが変更した項目だけを更新するやり方もある。この場合には重なりあわないAとBが両立する。
UPDATE TABLEXXX SET A=2 WHERE KEY=1 Aさん
UPDATE TABLEXXX SET B=2 WHERE KEY=1 Bさん
結果 A=2, B=2
先勝ちとは先に更新したほうが勝つポリシーだ。
同じデータを2者が同時に開いたとする、2者が別々の更新を行って更新を掛けたときに先に更新したものを正とし、遅れて更新処理をしたデータをはじくやり方である。
これの実装には2つやり方があって、更新する場合に更新前に読み取ったデータと一言一句同じデータの場合にだけ更新を許す方法がある。
VIsual StudioのDataAdapterウィザードで更新した場合のオプティミスティック同時実行制御をONにした場合の更新方法である。
UPDATE TABLEXXX SET A=2, b=2 WHERE KEY=1 AND A=0 AND B=0
この更新はとてもパフォーマンスが劣化するのでやめたほうがよい。
もう一つは更新カウンタ, バージョン管理をもつ方法である。
これは更新するたびに1カウントアップしていくこととし、SELECTした時とおなじ更新カウンタであるかをWhereに指定する。キーを変更していくという意味でロックの原始状態ともいえる。
UPDATE TABLEXX SET A=2, B=2, 更新カウンタ=3 WHERE KEY=1 AND 更新カウンタ=2
こうすることによって後から更新するものにとってキーが1で更新カウンタが2のデータは存在しなくなる。
後は更新する側の処理で更新した件数をチェックすればOKだ。0件だった場合には更新が失敗している。
最後はバッチ勝ちというやりかた。ちなみにこのへんの用語は私が言ってるだけで世間で通じないかもしれない(^^;
要はトランザクションを更新するものに優先度を付けるやり方。
夜間バッチなどにおいて、データのインポートなどがあるような場合に、データのインポート中などに更新されるのは都合が悪かったりする。
まず考えられる方策がテーブルロックである。ただしこれらは1トランザクションという意味で整合性であって、業務的な整合性とはまた違う。
また1トランザクションで出来る処理がすべてとは限らない。そうすると、業務的なロックをもつのかという選択になる。
独自ロック独自にフラグを管理するようにして、フラグがたっている場合にはトランザクション側は処理を遠慮するというやり方もある。
フラグ処理は一見簡単そうに思えるが非常に繊細な注意が必要。
一度あげたフラグを誰がおろすのか、異常終了したときのフラグは?、タイムアウトは?などだ。
バッチ処理で更新したデータ以外の更新は、更新要求という形でキューに保存しておくということも可能だ。
バッチ処理が動いている場合に、そのバッチの前に取得したデータを元にして、バッチ後に更新して良いのかということも考慮しなくては行けないため、前述の先勝ち後勝ちも当然同時に考慮しなくては行けない。
先勝ちをするけどもバッチが走ったら以前のデータはクリアするという場合には全データのカウンタを更新するか、どこかのテーブルのベース日付も必ずチェックするようにするとかいろいろな方式がある。
大体このへんが理解できれば業務処理におけるDB設計は出来たようなものである。(嘘)
最初のほうから後ろのほうに説明をしていく順に、実装やテストが難しくなるので注意されたし。(難度があがる)