- PR -

DBの排他管理

1
投稿者投稿内容
mso
会議室デビュー日: 2002/04/12
投稿数: 1
投稿日時: 2002-04-12 12:46
@ITのページでJSPを勉強し、
JSP+postgreSQLでWEBアプリを作成しました。

しかし、DBの排他管理(複数ユーザの同時更新)の記事は、
なかったので、どうしようかなと悩んでいます。

更新時刻チェックが一般的だとは思いますが、
皆さんどのようにやっていますか?
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2002-04-12 15:24
トランザクションの勉強をしてください。
というのがマットウな話なのでしょうが、HTTPでトランザクション扱うのはかなーり面倒です。なんかのライブラリでも使えばいいのかもしれませんが。

なので、1リクエストでトランザクションが完結するような設計をするのがすっきりするのでは。1リクエストで完結するなら、ふつうにロックして解除すればいいですし。

どうしてもやりたいときは、session に途中データをもたせとくなりして一気に更新するか、毎回更新でステータスフラグをつけておくか…などなど。

# という話ではないのかな… テーブルロックの話か?

[ メッセージ編集済み 編集者: しょむ 編集日時 2002-04-12 15:26 ]
edd
会議室デビュー日: 2002/04/21
投稿数: 11
お住まい・勤務地: 茨城県守谷市・東京都
投稿日時: 2002-04-21 04:33
msoさんがおっしゃっているのは、データ編集中に別の人が同じデータ
を変更した場合どうするかというお話だと思いますが。

やはりおっしゃるように、画面生成時にあらかじめ取得更新日時と更新
対象のデータの更新日時があっていることで、他のユーザーがそのデータ
を更新していないことを確認できるのではないかと思います。
ただ、きをつけなければならないのは、更新日時を秒単位でもっていると、
1秒以内の更新は、他ユーザーによって更新されていないと判断されて
しまうことです。
レアケースではありますが、これが問題になった場合があります。

このばあいは更新に日時ではなくてシーケンスなどの採番テーブルを使って
シーケンス番号を割り振ると良いと思います。


miki
大ベテラン
会議室デビュー日: 2001/09/21
投稿数: 174
お住まい・勤務地: 東京都八王子市
投稿日時: 2002-04-21 18:37
> msoさんがおっしゃっているのは、データ編集中に別の人が同じデータ
> を変更した場合どうするかというお話だと思いますが。

どうも、話がかみあっていませんね。

複数のユーザが同一データに並行アクセスしたとき、矛盾ないようにこの問題を解決してくれるのがトランザクション処理です。

トランザクションでは後から書き込みをおこなうとしても、前のトランザクションが処理中ならば待たされるので、そもそも更新時刻チェックは必要ありません。

ファイルベースのアプリならわかるのですが。

edd
会議室デビュー日: 2002/04/21
投稿数: 11
お住まい・勤務地: 茨城県守谷市・東京都
投稿日時: 2002-04-21 19:42
こんばんは、

>どうも、話がかみあっていませんね。

そうですね。
一応私の会解釈を書きますので、違いがあればご指摘ください。

まずトランザクションの話ですが、mikiさんのおっしゃるように1リクエストのトランザクションの間の排他制御はロックをかければすむと思います。 wait でロックをかければ他トランは待つだけですね。

前提として、ウェブアプリでリクエストを跨ぐトランザクションは現実的ではないのではないのでしょうか。 
なぜなら、そうしてしまうと画面をあけているあいだはトランザクション中になるわけで、レーコードのロック期間が異常に長くなってしまう危険があります。
タイムアウトでトランザクションを切る方法もありますが、それにそしてもトランザクション期間がながくなりDBのリソースを消費してしまうでしょう。

その前提でアプリを組み立てるとすると、トランザクションは1リクエスト内にとどめる構成にします。
データ更新のためには、まず、そのデータを取得、表示し、その内容をもとにユーザーは変更を行うはずです。
この場合ユーザーAが更新作業を行っている最中で更新ボタンをおすまえに、ユーザーBが更新をかけたとします。

トランザクションは切れていますからユーザーBは正常に更新が終了します。
このあとユーザーAが更新をかけてたときに正常終了していまうと、ユーザーBが行った修正は消えてしまいます。 
とくにユーザーAが触らなかった項目をユーザーBが変更していた場合は全く更新しなかったのと同じことになってしまいます。

ですから、データ編集を行ってから更新ボタンで更新処理をかけるときに、対象になるデータの更新日時から、画面上に取得したときの更新日時と同じであることを確認し、
同じである場合だけ更新処理を続行するようにします。 この排他方式はシーケンス番号でも行うことができます。

この排他制御は、同一レコードの更新を複数のユーザーが可能な場合に必要な処理です。業務要件上、同一レコードを複数ユーザーが更新できない構造ならば考慮する必要はありません。
まりり
ぬし
会議室デビュー日: 2001/12/05
投稿数: 329
投稿日時: 2002-04-22 10:29
eddさん:
> やはりおっしゃるように、画面生成時にあらかじめ取得更新日時と更新
> 対象のデータの更新日時があっていることで、他のユーザーがそのデータ
> を更新していないことを確認できるのではないかと思います。
> ただ、きをつけなければならないのは、更新日時を秒単位でもっていると、
> 1秒以内の更新は、他ユーザーによって更新されていないと判断されて
> しまうことです。
> レアケースではありますが、これが問題になった場合があります。

更新日および更新ユーザを持っておいて両方比較すればすみそうですね。
edd
会議室デビュー日: 2002/04/21
投稿数: 11
お住まい・勤務地: 茨城県守谷市・東京都
投稿日時: 2002-04-22 11:40
引用:

まりりさんの書き込み (2002-04-22 10:29) より:

更新日および更新ユーザを持っておいて両方比較すればすみそうですね。




そうですね。
しかし、ユーザーIDを複数の人で使い回さないという前提が必要ですね。
私のかかわったもので、支店には1つだけしかIDを割り振らずに、何人かで使い回す運用のものがありました。

運用の方を変えたほうがいいのはたしかなんですが、(笑)この場合は結局シーケンスで排他することになりました。
1

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