C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: レコードのSELECT,UPDATE処理時の排他制御について


(過去ログ 140 を表示中)

[トピック内 20 記事 (1 - 20 表示)]  << 0 >>

■81893 / inTopicNo.1)  レコードのSELECT,UPDATE処理時の排他制御について
  
□投稿者/ あさ (7回)-(2016/11/19(Sat) 10:33:09)

分類:[ASP.NET (VB)] 

2016/11/19(Sat) 13:14:38 編集(投稿者)
2016/11/19(Sat) 11:04:51 編集(投稿者)

レコードのSELECT,UPDATE処理時の排他制御について

お世話になります。
ASP.NET(VB),Windows10,SQLServer2014で開発しています。

ある予約システムを作成しています。
以下のような予約一覧テーブル(分かりやすくするために簡略化します)があるとします。
予約Noはオートナンバーです。

予約一覧テーブル
予約No 部屋No 氏名
10000  1    鈴木
10001  2    山田
10002  3    佐藤

新たに予約を行う際には、いきなりUPDATEではなく、
まずは部屋NoのMax値(ここでは3)をSELECTして、
+1をして、部屋数の定数内であることを確認し、それから、
UPDATE(INSERTによる)します。

一般的に、テーブル更新時の排他制御はASP.NETの場合、
更新時のオプティミスティックロックで行うとのことですが、
部屋Noは主キーではないため、
以下のような同時更新が成立してしまうのではないかと考えます。

予約No 部屋No 氏名
10000  1    鈴木
10001  2    山田
10002  3    佐藤
10003  4    木村
10004  4    森田

こうなってしまいますと、部屋No=4が重複していまい、ダブルブッキングになってしまいます。

そこで、他のユーザーがSELECT,UPDATE(INSERTによる)のトランザクション処理を行っている間は、
他のユーザーは待機する、ようにしたいのですが、
(これはペシミスティックロックということになりますでしょうか)
今現在他のユーザーが処理中であるということを他ユーザーが知るための実装方法には、
どのようなものがありますでしょうか。

不勉強で申し訳ありません。

どうぞよろしくお願いします。

※例えば、すごく単純ですが、このような方法はいかがでしょうか。
この目的のためにApplication変数を使うのは、
サーバーへの負担が大きいでしょうか。

SELECT,UPDATE(INSERTによる)処理に、
以下のコードを加える。

If Application("yoyakutyu") IsNot Nothing Then
  If Application("yoyakutyu")="他のユーザーが予約処理中" Then
    MsgBox("ただいま他のユーザーが予約処理中です。")
   Exit Sub
End If
Else
  Application("yoyakutyu")="他のユーザーが予約処理中"
  (SELECT,UPDATE(INSERTによる)処理)
  Application.Remove("yoyakutyu")
End If


引用返信 編集キー/
■81894 / inTopicNo.2)  (削除)
□投稿者/ -(2016/11/19(Sat) 12:19:17)
この記事は(管理者)削除されました
引用返信 編集キー/
■81895 / inTopicNo.3)  Re[2]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ あさ (8回)-(2016/11/19(Sat) 13:13:08)
No81894 (WebSurfer さん) に返信

ありがとうございます。

会員制の予約システムで、予約可能時間にはある程度の幅があり、
会員の数もそこまでたくさんではないとすると、
SELECT,UPDATE処理にかかる時間は1秒前後なので、
アプリケーション変数の方法でもそこまで重複することはないかな、
とも考えていますが、
たまたま同時にいくつもの処理が重なった場合、
ユーザーは何度も何度も待たされてしまいますね。
こればかりは読めませんね。

予約一覧テーブルにあらかじめ全部屋のレコード行が入っている場合、
各レコードが編集中かどうかをチェック出来ると思うのですが、
ここでのUPDATEは、大変失礼しました、INSERTでした。

ですが、ご紹介頂きましたご著書の方法、とても参考になりそうです。
予約システム全体の仕組みについても、再考してみたいと思います。
著書、拝読したいと思います。

とても助かりました。
ありがとうございます。

引用返信 編集キー/
■81915 / inTopicNo.4)  (削除)
□投稿者/ -(2016/11/23(Wed) 00:33:22)
この記事は(管理者)削除されました
引用返信 編集キー/
■81930 / inTopicNo.5)  (削除)
□投稿者/ -(2016/11/24(Thu) 14:57:54)
この記事は(管理者)削除されました
引用返信 編集キー/
■81932 / inTopicNo.6)  (削除)
□投稿者/ -(2016/11/24(Thu) 15:33:51)
この記事は(管理者)削除されました
引用返信 編集キー/
■81937 / inTopicNo.7)  Re[6]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ あさ (9回)-(2016/11/24(Thu) 17:51:33)
2016/11/24(Thu) 18:13:35 編集(投稿者)

No81932 (WebSurfer さん) に返信


他の方からもまだ何か投稿があるかもしれないということと、
頂きました解決方法をまだ実際に試し成功しきれていないということから、
まだ「解決済み」にはしておりませんでした。

「解決済み」にさせて頂き、不明な点等が出てきましたら、
また、チェックを外してお伺いさせて頂きます。

よろしくお願いします。
解決済み
引用返信 編集キー/
■81938 / inTopicNo.8)  Re[5]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ あさ (10回)-(2016/11/24(Thu) 18:15:13)
No81930 (Jitta さん) に返信

解決に向けて尽力します。
ありがとうございます。
解決済み
引用返信 編集キー/
■81942 / inTopicNo.9)  (削除)
□投稿者/ -(2016/11/24(Thu) 18:32:53)
この記事は(管理者)削除されました
引用返信 編集キー/
■81948 / inTopicNo.10)  (削除)
□投稿者/ -(2016/11/24(Thu) 19:17:46)
この記事は(管理者)削除されました
引用返信 編集キー/
■81949 / inTopicNo.11)  (削除)
□投稿者/ -(2016/11/24(Thu) 19:22:29)
この記事は(管理者)削除されました
引用返信 編集キー/
■81950 / inTopicNo.12)  (削除)
□投稿者/ -(2016/11/24(Thu) 21:23:52)
この記事は(管理者)削除されました
引用返信 編集キー/
■81955 / inTopicNo.13)  Re[9]: (削除)
□投稿者/ 管理人 中博俊 (1回)-(2016/11/25(Fri) 00:29:39)
一部の記事を削除しました。
引用返信 編集キー/
■81956 / inTopicNo.14)  Re[10]: (削除)
□投稿者/ WebSurfer (1083回)-(2016/11/25(Fri) 01:48:21)
No81955 (管理人 中博俊 さん) に返信
> 一部の記事を削除しました。

全削除ですか・・・
引用返信 編集キー/
■81972 / inTopicNo.15)  Re[10]: (削除)
□投稿者/ WebSurfer (1084回)-(2016/11/25(Fri) 20:41:45)
No81955 (管理人 中博俊 さん) に返信

質問者さんが、

> ですが、ご紹介頂きましたご著書の方法、とても参考になりそうです。
> 予約システム全体の仕組みについても、再考してみたいと思います。
> 著書、拝読したいと思います。
>
> とても助かりました。
> ありがとうございます。

と書いた私のレス No81894 ぐらいは復活させてもらえませんか?
それまで削除するのはいくら管理人と言え暴挙としか思えません。
引用返信 編集キー/
■81975 / inTopicNo.16)  Re[1]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ Jitta (224回)-(2016/11/26(Sat) 08:44:37)
No81893 (あさ さん) に返信
> ある予約システムを作成しています。

 ここに書かれているのは「予約をする」ことのみです。
では、「約が実行された」時は、どうするのでしょうか。

> 以下のような予約一覧テーブル(分かりやすくするために簡略化します)があるとします。
> 予約Noはオートナンバーです。
>
> 予約一覧テーブル
> 予約No 部屋No 氏名
> 10000  1    鈴木
> 10001  2    山田
> 10002  3    佐藤
>
> 新たに予約を行う際には、いきなりUPDATEではなく、
> まずは部屋NoのMax値(ここでは3)をSELECTして、
> +1をして、部屋数の定数内であることを確認し、それから、
> UPDATE(INSERTによる)します。

簡略化してあるということですが。
当然、日付があるのでしょう。
連泊するときは、どうなるのでしょうか。1日ごとに1レコード使うのか、ということです。
その場合、2泊目は、部屋Noは、どうするのでしょうか。
1日目の予約が1件、2日目の予約が0件の場合、1日目の部屋Noは2になります。2日目の部屋Noは何番?
ここで「2」にすると、2日目が1日目になる人の部屋Noはどうなる?
また、1,2,3と予約が埋まった後、2の人がキャンセルしたら?

と、コードを考える前に考えなければならないことが、まだまだあるように思います。
引用返信 編集キー/
■82040 / inTopicNo.17)  Re[2]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ あさ (11回)-(2016/12/02(Fri) 10:24:35)
No81975 (Jitta さん) に返信

ご返事遅れましてすみません。
今回作成している予約システムは、宿泊業のものではなく、
一時保育に関するものでして。
なので、基本的には当日1日の特定時間のみ使用、1日ごとの利用になります。
もし、連続で予約を入れたい場合は、それぞれの予約で、部屋NOも
変わり得ます。
予約が確定された、予約者が実際に来た、預けた、迎えに来た、精算して終了した、
の各段階をフラグで管理します。

これらのことを踏まえまして、お答えします。

> 1日目の予約が1件、2日目の予約が0件の場合、1日目の部屋Noは2になります。2日目の部屋Noは何番?
2日目の部屋NOは1になります。

> ここで「2」にすると、2日目が1日目になる人の部屋Noはどうなる?
2日目の予約で部屋NO「2」が埋まっている場合、「1」が空いていれば「1」になります。
「1」が空いてなければ「3」になります。
実際のコードでは、すでに埋まっている部屋NOを昇順で並べ、空きがあるかを検索、空きがなければ+1します。

> また、1,2,3と予約が埋まった後、2の人がキャンセルしたら?
2の人がキャンセルした場合は、次の予約は「2」に入ります。

ありがとうございます。

> ■No81893 (あさ さん) に返信
>>ある予約システムを作成しています。
>
>  ここに書かれているのは「予約をする」ことのみです。
> では、「約が実行された」時は、どうするのでしょうか。
>
>>以下のような予約一覧テーブル(分かりやすくするために簡略化します)があるとします。
>>予約Noはオートナンバーです。
>>
>>予約一覧テーブル
>>予約No 部屋No 氏名
>>10000  1    鈴木
>>10001  2    山田
>>10002  3    佐藤
>>
>>新たに予約を行う際には、いきなりUPDATEではなく、
>>まずは部屋NoのMax値(ここでは3)をSELECTして、
>>+1をして、部屋数の定数内であることを確認し、それから、
>>UPDATE(INSERTによる)します。
>
> 簡略化してあるということですが。
> 当然、日付があるのでしょう。
> 連泊するときは、どうなるのでしょうか。1日ごとに1レコード使うのか、ということです。
> その場合、2泊目は、部屋Noは、どうするのでしょうか。
> 1日目の予約が1件、2日目の予約が0件の場合、1日目の部屋Noは2になります。2日目の部屋Noは何番?
> ここで「2」にすると、2日目が1日目になる人の部屋Noはどうなる?
> また、1,2,3と予約が埋まった後、2の人がキャンセルしたら?
>
> と、コードを考える前に考えなければならないことが、まだまだあるように思います。
引用返信 編集キー/
■82041 / inTopicNo.18)  Re[3]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ あさ (12回)-(2016/12/02(Fri) 10:24:50)
No82040 (あさ さん) に返信
> ■No81975 (Jitta さん) に返信
>
> ご返事遅れましてすみません。
> 今回作成している予約システムは、宿泊業のものではなく、
> 一時保育に関するものでして。
> なので、基本的には当日1日の特定時間のみ使用、1日ごとの利用になります。
> もし、連続で予約を入れたい場合は、それぞれの予約で、部屋NOも
> 変わり得ます。
> 予約が確定された、予約者が実際に来た、預けた、迎えに来た、精算して終了した、
> の各段階をフラグで管理します。
>
> これらのことを踏まえまして、お答えします。
>
>>1日目の予約が1件、2日目の予約が0件の場合、1日目の部屋Noは2になります。2日目の部屋Noは何番?
> 2日目の部屋NOは1になります。
>
>>ここで「2」にすると、2日目が1日目になる人の部屋Noはどうなる?
> 2日目の予約で部屋NO「2」が埋まっている場合、「1」が空いていれば「1」になります。
> 「1」が空いてなければ「3」になります。
> 実際のコードでは、すでに埋まっている部屋NOを昇順で並べ、空きがあるかを検索、空きがなければ+1します。
>
>>また、1,2,3と予約が埋まった後、2の人がキャンセルしたら?
> 2の人がキャンセルした場合は、次の予約は「2」に入ります。
>
> ありがとうございます。
>
>>■No81893 (あさ さん) に返信
> >>ある予約システムを作成しています。
>>
>> ここに書かれているのは「予約をする」ことのみです。
>>では、「約が実行された」時は、どうするのでしょうか。
>>
> >>以下のような予約一覧テーブル(分かりやすくするために簡略化します)があるとします。
> >>予約Noはオートナンバーです。
> >>
> >>予約一覧テーブル
> >>予約No 部屋No 氏名
> >>10000  1    鈴木
> >>10001  2    山田
> >>10002  3    佐藤
> >>
> >>新たに予約を行う際には、いきなりUPDATEではなく、
> >>まずは部屋NoのMax値(ここでは3)をSELECTして、
> >>+1をして、部屋数の定数内であることを確認し、それから、
> >>UPDATE(INSERTによる)します。
>>
>>簡略化してあるということですが。
>>当然、日付があるのでしょう。
>>連泊するときは、どうなるのでしょうか。1日ごとに1レコード使うのか、ということです。
>>その場合、2泊目は、部屋Noは、どうするのでしょうか。
>>1日目の予約が1件、2日目の予約が0件の場合、1日目の部屋Noは2になります。2日目の部屋Noは何番?
>>ここで「2」にすると、2日目が1日目になる人の部屋Noはどうなる?
>>また、1,2,3と予約が埋まった後、2の人がキャンセルしたら?
>>
>>と、コードを考える前に考えなければならないことが、まだまだあるように思います。
引用返信 編集キー/
■82055 / inTopicNo.19)  Re[4]: レコードのSELECT,UPDATE処理時の排他制御について
□投稿者/ Jitta (233回)-(2016/12/02(Fri) 20:42:19)
No82041 (あさ さん) に返信
>>今回作成している予約システムは、宿泊業のものではなく、
>>一時保育に関するものでして。
>>なので、基本的には当日1日の特定時間のみ使用、1日ごとの利用になります。

リラクゼーションサロンに行くのですが、そこの予約システムは、予約可能なすべての時間、部屋が表示されます。
先に、キャンセルがあり得るのか、尋ねました。あるということでした。最初の投稿には「最大値+1を新しい部屋番号とする」とあります。
そうすると、キャンセルをした時点で今考えているロジックが使えなくなります。では、キャンセルがある日と、ない日でロジックを変えますか?
それもナンセンスです。
では、日の終わりなどに予約できるようになった日の分のレコードを作り、予約済みかどうかを見るようにしてはどうでしょうか。
すると、行ごとの楽観的ロックで済むようになるのではないでしょうか。
引用返信 編集キー/
■82059 / inTopicNo.20)  Re[5]: レコードのSELECT,UPDATE処理時の排他制御について
 
□投稿者/ あさ (17回)-(2016/12/04(Sun) 10:26:33)
No82055 (Jitta さん) に返信

ありがとうございます。
キャンセルについては、キャンセルがあるかないかでロジックを変えていません。
ご説明不足でした。
簡単に申しますと、こういうアルゴリズムです。

当日宿泊可能な部屋NO(A):1 2 3 4 5 6 7 8 9 10
現在予約されている部屋NO(B):1 2 3 5 6 7

Aの1〜10をループさせて、Bに該当があるかないかを調べます。
例では「4」がBにありませんので、次の予約は「4」になります。
その次は、「8」になります。

予約について、先にマスタを全部作っておく、について。
ある1日のある部屋における時間配分が固定的であれば、その方がいいなと思っています。
例えば、リラクゼーションサロンだと、1セッションが1時間とすると、こういうことですよね。

部屋NO=1
・9〜10 予約未/済
・10〜11 予約未/済
・11〜12 予約未/済
・13〜14 予約未/済


ホテルにおいても、1泊という単位がありますよね。
列車においても、駅という固定的な区分があります。

一時保育の場合は、会員によって、選択できる時間の幅がまったく別々なのです(ただし30分単位)。
ある会員は30分、ある会員は3時間、だったりするのです。

そうすると、予約レコードにおいては、
部屋NO=1
9時〜9時半
10時〜13時
…という具合になります。

もしこれを、固定的なやり方で行おうとすると、
部屋NO=1
9〜930 済
930〜1000 
1000〜1030 済
1030〜1100 済
1100〜1130 済
1130〜1200 済
1200〜1230 済
1230〜1300 済

ただこうなりますと、1予約=1行ではなくなってしまい、1行単位でのロック管理ができなくなってしまいます。
予約する人はそれぞれの時間帯を個別に予約するわけではなく、
何時から何時まで、を自分で選択して予約します。

また、これも一時保育ならではの事情があるのですが、
サロンのセッションや駅の乗り換えは時間厳守ですね。
セッションの場合、前の人が万一長引いて少し待つことはあると思います。
電車の場合は、乗り遅れたらアウトですね。
一時保育の場合、勤務している親御さんが、準備や交通上の理由などで、
お預け、お迎えが予約した時間通りには行かない場合が想定されます。
時間が来たからとお子さんを追い出すわけにもいきません。

なので、
例えば、
同日午後に予約したい方がいて、
部屋NO=1の午前が埋まっていて、午後が空いていて、
部屋NO=2が空いている場合は、
部屋NO=2を割り当てるようにしています。
部屋NO=1の午前の人が万一長引いてしまった場合に重ならないようにするためです。

このロジックを適用する際に、
1予約=1行の方が管理しやすいという点があります。

これらの事情がありますが、楽観的ロックで出来ないものか、
検討してみます。

ありがとうございます。

> ■No82041 (あさ さん) に返信
> >>今回作成している予約システムは、宿泊業のものではなく、
> >>一時保育に関するものでして。
> >>なので、基本的には当日1日の特定時間のみ使用、1日ごとの利用になります。
>
> リラクゼーションサロンに行くのですが、そこの予約システムは、予約可能なすべての時間、部屋が表示されます。
> 先に、キャンセルがあり得るのか、尋ねました。あるということでした。最初の投稿には「最大値+1を新しい部屋番号とする」とあります。
> そうすると、キャンセルをした時点で今考えているロジックが使えなくなります。では、キャンセルがある日と、ない日でロジックを変えますか?
> それもナンセンスです。
> では、日の終わりなどに予約できるようになった日の分のレコードを作り、予約済みかどうかを見るようにしてはどうでしょうか。
> すると、行ごとの楽観的ロックで済むようになるのではないでしょうか。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -