設問3 予約管理機能の不具合について(1)~(4)に答えよ。
(1) 表7を完成させるために、【h】~【l】に入れる適切な字句又は数字を答えよ。
【h】:42
【i】:α
【j】:60
【k】:β
【l】:60
解説
表7の穴埋め問題です
まず本文抜粋
不具合の発見を受けて、図5及び図6について、顧客αと顧客βがそれぞれのブラウザから操作を行うことを想定して、ソースコードレビューを行った。
その結果、顧客αと顧客βが、画面2で空き状態であった同一の予約枠をほぼ同時に選択した場合、表7に示す順序で各処理が完了すると、顧客αの仮予約がデータベースに反映されないことが確認できた。
ざっくり要約すると「αβが同時に同一の予約枠をほぼ同時に選択した場合に、αの仮予約がデータベースに反映されない」となりますが、原因は簡単「αの仮予約の次の瞬間に、βも仮予約したからαの仮予約が消えた」と考えられます。
図5 サーブレット"WakuClick" 抜粋
1~39: (管理人省略)
40: // 選択された予約枠の予約状況を参照する
41: psSel.setString(1, rsvDate); psSel.setString(2, rsvTime); psSetl.setString(3, rsvBiyoshi);
42: ResultSet rs = psSel.executeQuery();
43: rs.next(); ← [表7手順1 予約枠の予約状況を参照!]
44: long lastDateTime = rs.getLong("LastUpdate");
45: // 現在の時刻を取得する
46: long nowDateTime = new Date().getTime();
47: // 既に仮予約状態であった場合、仮予約の最終更新日時を確認し、TIMEOUT_KARI経過後なら空きにする
48: int rsvStatus = rs.getInt("Status");
49: if (rsvStatus == RSV_KARI) {
50: if ((nowDateTime - lastDateTime) > TIMEOUT_KARI) {
51: rsvStatus = RSV_AKI;
52: }
53: }
54: // 予約状況が空きであることを確認し、仮予約処理を行う
55: if (rsvStatus == RSV_AKI) {
56: psUp.setInt(1, RSV_KARI); psUp.setString(2, loginUserID); psUp.setString(3, "");
57: psUp.setString(4, ""); psUp.setLong(5, nowDateTime);
58: psUp.setString(6, rsvDate);
59: psUp.setString(7, rsvTime); psUp.setString(8, rsvBiyoshi);
60: psUp.executeUpdate(); ← [仮予約の更新を行うところ]
61: (省略)[図6の処理を引き継ぐために、選択した予約枠の情報をサーブレットのセッション情報に保存する]
62: (省略)[画面3のHTML出力を行う]
63~ (管理人省略)
図5 サーブレット"WakuClick" 抜粋終わり
肝になるのは、42行目の[予約枠の予約状況を参照!]と60行目の[仮予約の更新を行うところ]です。
一般的なRDBMSを使用している場合、αの更新の後に、βが更新して上書きというシナリオは、2パターン考えられます。
パターン1
1 |
αが[予約枠の予約状況を参照!] |
2 |
αが[仮予約の更新を行うところ] ここでαのトランザクションが行ロック |
3 |
βが[予約枠の予約状況を参照!] |
4 |
βが[仮予約の更新を行うところ] ロック開放待ち |
5 |
αがコミットと同時にロック開放 |
6 |
βがコミット |
パターン2
1 |
αが[予約枠の予約状況を参照!] |
2 |
βが[予約枠の予約状況を参照!] |
3 |
αが[仮予約の更新を行うところ] ここでαのトランザクションが行ロック |
4 |
βが[仮予約の更新を行うところ] ロック開放待ち |
5 |
αがコミットと同時にロック開放 |
6 |
βがコミット |
今回の問題では、表7の順序2に「β」が指定されているのでパターン2が該当するので、表7は以下のようになります。
表7 仮予約が無効になる処理の順序
順序 |
対象の顧客 |
処理 |
1 |
α |
図5の42行目 |
2 |
β |
図5の【 42 】行目 |
3 |
【 α 】 |
図5の【 60 】行目 |
4 |
【 β 】 |
図5の【 60 】行目 |
最終更新:2013年08月31日 19:00