@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

リモートDB更新の排他制御方法

1
投稿者投稿内容
ラフレシア
会議室デビュー日: 2006/01/30
投稿数: 7
投稿日時: 2006-12-01 12:50
お世話になっております。
スマートな実現方法が思いつかず悩んでおります。

環境:
.Net Framework 1.1
データベースは、SQL Server 2000
複数台のクライアント(Windows Formアプリ)から、サーバ上のDBにアクセスし、
DBを参照・更新する。クライアントは、DB編集用の特定の画面Aを持っている。
サーバとクライアントは、ローカルなネットワークで接続されている。

更新の排他制御はDBに任せるつもりだったのですが、
「他のクライアントで画面Aを開いているときは、画面Aを開くことができない。
更新時にではなく、編集開始時にブロックする。」
という要件を追加されてしまいました。
どうしたら、もっともスマートに解決できるでしょう?

(案1)…ミーティング中に提案されたもの
DBに編集中であるという情報を書き込む
この情報があるあいだは、画面Aを開かない。
クライアントが異常終了した場合は、編集中情報を消すツールを用意する。

(案2)
.Net Remotingをシングルトンで作成。
オブジェクトの内部に使用者(使用中)の情報を持つ。
lifetimeを3時間くらいにして、画面Aを開きっぱなしにしていたらエラーにする!
クライアントが異常終了しても、3時間後には復活。

(案3)
Web Serviceで共有変数を使う?

何か良い方法はないでしょうか?
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-12-01 13:01
スマートかどうかは分かりませんが、そこまでガチガチにしていいなら、
(案4)
データを参照する段階でトランザクションを開始し、共有ロックすらとれないぐらいロックする。
_________________
囚人のジレンマな日々
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2006-12-01 22:54
同じくスマートではないです。

排他制御用の「テーブル」を用意しアプリ起動時に排他テーブルロックを利用してSELECT。
コネクションは保持したまま。もし排他ロックで例外が発生した際はアプリ終了。
データ更新などは別コネクションを利用して行う。

これであれば異常終了してもコネクションをクエリアナライザとかからKillして
あげれば終わりますね。

ネックはDBのライセンスです・・・。しかしこんな手段でいいのだろうか、という不安もあります。
ヒトカゲ
会議室デビュー日: 2006/11/29
投稿数: 6
お住まい・勤務地: 大阪
投稿日時: 2006-12-01 23:32
ASP.NETは使用したことがありませんが…

 nullableなフィールドを用意し、編集中はそこに時刻を書き込む。
 編集中は n 分毎ぐらいでそのフィールドを更新する。
 他のプロセスはそのフィールドがnull、もしくは (n+1) 分以前であれば編集可能と見なす。

という感じのことなら以前行ったことがあります。
私の時はAjaxで5分毎にCGIに編集中であることを知らせていました。

利用できるかどうか分かりませんが御参考まで。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2006-12-01 23:38
(案1) の変形で、いわゆるチケットを発行するようにして、「占有」の証として、排他したい行にチケット(の識別子)を書き込んでおけばいいんじゃないでしょうか。
(列がNULLなら誰も占有していないこととします)

あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-12-02 00:14
引用:

ラフレシアさんの書き込み (2006-12-01 12:50) より:
スマートな実現方法が思いつかず悩んでおります。



長期間の排他ロック自体がスマートじゃないので無理でしょう。

引用:

(案1)…ミーティング中に提案されたもの
DBに編集中であるという情報を書き込む
この情報があるあいだは、画面Aを開かない。
クライアントが異常終了した場合は、編集中情報を消すツールを用意する。



ロックレコード/カラムにしろ、トランザクションを使うにしろ、
この手のDBを利用した方法が一番普通でしょう。

ロックレコードを使う場合の異常終了対策は、レコードを厳密なものと扱わずに、
「誰かが編集しているみたいです」程度に扱った方がいいんじゃないでしょうか。
アラートを出して、利用者が望む場合はロックを無視して編集可能にします。

編集画面を複数人に開かせない理由は、

1. 並行トランザクションの制御を簡素化したい(簡素化されるかは別ですが)
2. 編集後に更新に失敗する状況を回避したい(楽観的ロックを用いた場合)

のどちらか(あるいは両方)の場合が多い思います。

警告にとどめれば、ロックレコードにゴミが残っていた場合に管理者が
対応しなければならない状況も、編集後の更新失敗も回避できるわけです。

さらに、レースコンディションや警告を無視した場合の更新の競合に関しては、
バージョニングやタイムスタンプによる楽観的ロック戦略を用いれば解決です。

まあ、実装の手間は多少余計にかかると思いますが。
ラフレシア
会議室デビュー日: 2006/01/30
投稿数: 7
投稿日時: 2006-12-03 20:22
アドバイスありがとうございます。
> 長期間の排他ロック自体がスマートじゃないので無理でしょう。
一言もありません…。

排他制御用にテーブル追加。(既存のテーブルには手を触れたくない)
ユーザ(クライアント情報)と編集時刻を書く。
というのが一番でしょうか?
管理者が対応しなければならない状況は減らしたいので、
細かい実現手段はもう少し検討します。

ところで皆様、遠隔からのDB更新のAPIにWeb Serviceはお使いでしょうか?
今までは参照のみWeb Serviceで提供していたのですが、更新の事例はあまり
知らなくて…。Well Known Portの使用は禁止されているので、
Web Serviceか .Net Remotingか。これもまた迷っています。




[ メッセージ編集済み 編集者: ラフレシア 編集日時 2006-12-03 20:23 ]

[ メッセージ編集済み 編集者: ラフレシア 編集日時 2006-12-03 20:23 ]
1

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