データベーススペシャリスト 2020年 午後1 問02
データベースの実装に関する次の記述を読んで、設問1〜3に答えよ。
劇場運営会社の Y 社は、オンラインチケット販売システム (以下、チケット販売システムという)を構築してインターネットでのチケットの申込みを受け付けている。Y社ではチケット販売システムを刷新し、新たにプレイガイドなどでのチケット販売委託を進めることになった。
〔RDBMS の主な仕様〕
チケット販売システムに用いている RDBMS の主な仕様は、次のとおりである。
1.ISOLATION レベル
選択できるトランザクションの ISOLATION レベルとその排他制御の内容は、表1のとおりである。
ロックは行単位で掛ける。 共有ロックを掛けている間は、他のトランザクションからの対象行の参照は可能であり、変更は共有ロックの解放待ちとなる。 専有ロックを掛けている間は、他のトランザクションからの対象行の参照、変更は専有ロップクの解放待ちとなる。

2.レプリケーション機能
(1) 1か所のデータを複数か所に複製する機能、複数か所のデータを1か所に集約する機能、及び両者を組み合わせて双方向に反映する機能がある。これらの機能を使用すると、一方のテーブルへの挿入・更新・削除を他方に自動的に反映させることができる。
(2) トランザクションログを用いてトランザクションと非同期に一定間隔でデータを反映するバッチ型と、レプリケーション元のトランザクションと同期してデータを反映するイベント型がある。
① バッチ型では、テーブルごとに、レプリケーションの有効化、無効化をコマンドによって指示することができる。 無効化したレプリケーションを有効化するときには、蓄積されたトランザクションログを用いてデータを反映する。
② イベント型では、レプリケーション先への反映が失敗すると、レプリケーション元の変更はロールバックされる。
(3) 列の選択、行の選択及びその組合せによって、レプリケーション先のテーブルに必要とされるデータだけを反映することができる。
〔チケット販売システムの概要〕
チケット販売システムは、空席管理システムと販売管理システムで構成される。 オンラインチケット販売時には、空席管理システムで空席を確認した後に座席を確保し、販売管理システムでチケット情報を保持する。
〔チケット販売システムのテーブル〕
空席管理システムと販売管理システムのそれぞれの主なテーブルのテーブル構造は、図 1,2のとおりである。 索引は、主キー及び外部キーに定義している。


〔チケット販売業務の概要〕
1.テーブル及び列の設定
(1) 会場と座席
① 会場には、一意な会場番号を付与して、都道府県、住所、座席図などを設定する。
② 座席には、会場ごとに一意な座席番号を付与して、席種 ( 'S'、'A'、'B'など) を設定する。
(2) 公演と席種料金
① 公演には、一意な公演番号を付与する。 公演開催明細には、公演日時 (公演日、開演時刻)ごとに、開場時刻、公演会場番号、販売開始日などを設定する。
② 席種料金には、公演の席種ごとに料金を設定する。
(3) 席種在庫と座席状況
① 席種在庫には、席種ごとの空席数をもつ。 座席の購入が確定したら空席数を減らし、購入された座席がキャンセルされたら空席数を戻す。
② 座席状況には、公演開催明細ごとの全ての座席の状況をもつ。 販売開始時には、空席フラグはオン、仮予約フラグはオフとする。 座席の購入処理中は仮予約フラグをオンにする。 座席の購入が確定したら、空席フラグをオフにして仮予約フラグをオフにする。
(4) チケット
① チケットには、公演開催明細ごとに、全ての座席番号と席種を設定する。
② 未販売のチケットは、購入フラグをオフに、購入番号を NULL に設定する。
③ チケットの購入を申し込まれたら、購入フラグをオンにする。 購入が確定したら、購入番号を設定する。
2.チケットの購入
(1) チケットを購入するためには、会員登録をする必要がある。
(2) 会員は、チケットの検索を行って、チケット情報一覧を表示する。 チケット情報は、公演名・公演日・開演時刻の昇順、料金の降順に出力される。
(3) 会員は、チケット情報一覧から、空席のある公演の席種を選択する。 その後、枚数を指定し、空席の座席番号を希望枚数分指定する。
(4) 会員は、決済を行い、決済が成立すれば購入が確定する。
〔チケット情報一覧を出力する SQL 文の設計〕
空席管理システムから、公演日が2020年4月かつ都道府県が東京のチケット情報一覧の出力の例を図 3, 出力する SQL文の構文を図4に示す。


〔オンラインチケット販売処理の設計〕
チケット販売委託のため、空席管理システムは、プレイガイドなどの外部委託先にも公開する。このために、空席管理システムの空席確認、仮予約の処理の見直しを行った。 見直しに当たって、同時実行されたトランザクションのやり直しが極力発生しないようにする方針とした。
ある会員が複数のチケットを購入することを想定して、チケットの販売処理について検討した。 その概要を図5に示す。
図5では、会員の意思で購入を途中でキャンセルした場合、空席でない座席があり購入が失敗した場合、又はその他のエラーが発生した場合の、途中までの処理を取り消すための例外処理を省略している。

図5の内容のレビューを行った。レビューでの指摘内容と対策を表2に示す。

〔レプリケーションの設計 〕
チケット販売委託先に、空席管理システムを介して、空席情報を表示するサービスも提供する。そのため、データベースへの大量のアクセスによるロックの解放待ちの多発が見込まれるので、空席情報表示用のレプリケーション先のテーブル(以下、レプリカデータという)を作成することにした。 レプリカデータのテーブル構造は、図1 の空席管理システムの主なテーブルと同等なものとし、サービスの提供先ごとにレプリカデータを用意する。 レプリカデータの運用について図6に示す。 さらに、図6の内容のレビューを行った。 レビューでの指摘内容と対策を表3に示す。



設問1:
〔チケット情報一覧を出力するSQL文の設計〕について、図4中の(a)〜(g)に入れる適切な字句を答えよ。
模範解答
a:CASE WHEN
b:IS NULL
c:LEFT [OUTER] JOIN
d:BETWEEN
e:AND
f:ORDER BY
g:DESC
解説
解答の論理構成
-
空席判定部 (a)(b)
図4は
「( (a) A2.空席数 (b) THEN 'X' ELSE 'O' END ) AS 空席情報」
と示されています。空席数が NULL なら売切れ (×) にしたいので、SQL 標準の条件式 CASE WHEN … IS NULL THEN … を用いるのが自然です。したがって
(a) CASE WHEN
(b) IS NULL
となります。 -
テーブル結合部 (c)
A2 は「空席数 > 0」で抽出済みの在庫ビューです。これに一致しない行でも公演情報は一覧に載せる必要があるため、外部結合が必須です。方向は「会場、A1」に対し A2 をくっつけるので LEFT OUTER JOIN が正解です。 -
日付条件部 (d)(e)
条件句は
「公演日 (d) '2020-04-01' (e) '2020-04-30'」
とあり、期間検索を1文で表す BETWEEN … AND 構文が典型です。従って
(d) BETWEEN
(e) AND
となります。 -
並び替え部 (f)(g)
要件「公演名・公演日・開演時刻の昇順、料金の降順」に対応するため、 ORDER BY 公演名、公演日、開演時刻、料金 DESC
のように記述します。図4の (f)…(g) に該当するのは
(f) ORDER BY
(g) DESC
です。
誤りやすいポイント
- IS NULL ではなく A2.空席数 = 0 と書くと、空席数列が存在しない行を売切れ扱いできません。
- INNER JOIN を選ぶと在庫が無い席種が一覧に出ず要件違反となります。
- BETWEEN を使わず >= と <= を別々に書くと (e) を何にするか迷って誤答しがちです。
- ORDER BY で料金だけ DESC にする場合、列ごとに昇降を個別指定できることを忘れ、全体を DESC 指定してしまうケースがあります。
FAQ
Q: OUTER を省略した LEFT JOIN でも良いですか?
A: 多くの RDBMS で動きますが、図1のように「外部結合」を強調している問題では LEFT OUTER JOIN と明示するのが無難です。
A: 多くの RDBMS で動きますが、図1のように「外部結合」を強調している問題では LEFT OUTER JOIN と明示するのが無難です。
Q: 空席判定で COALESCE を使う方法は誤りですか?
A: COALESCE(A2.空席数,0) のように書き、0 なら × と判定する実装でも論理上は可能ですが、図4の (a)(b) が2か所の穴埋めである以上 CASE WHEN … IS NULL の形が出題意図に沿います。
A: COALESCE(A2.空席数,0) のように書き、0 なら × と判定する実装でも論理上は可能ですが、図4の (a)(b) が2か所の穴埋めである以上 CASE WHEN … IS NULL の形が出題意図に沿います。
関連キーワード: CASE式、外部結合、BETWEEN句、NULL判定、ソート順序
設問2:〔オンラインチケット販売処理の設計〕 について(1)、(2)に答えよ。
(1)表2中の(あ)〜(お)に入れる適切な字句を答えよ。
模範解答
あ:同じ座席 又は 同じチケット
い:購入できない
う:購入番号
え:NULL
お:コミット
解説
解答の論理構成
- 表2の指摘文
「複数の会員が、ほぼ同時に、(あ)を購入しようとした場合…」から、対象は同一リソースである「同じ座席」と判断。 - 先行トランザクション完了後に判明する内容
「…待たされてから、(い)ことが判明する。」──失敗理由は在庫切れなので「購入できない」。 - 対策のキーワード
「③の処理の購入フラグをオンにする条件に(う)が(え)であることを追加」
・図2「チケット」表にある未購入判定列は「購入番号」。
・未割当は「NULL」で管理されている(〔チケット〕1.(4)②より「購入番号を NULL に設定する」)。 - ロック期間短縮策
「1座席ごとに処理して(お)するよう変更する。」
1件処理後に早期確定させる操作は「コミット」。 - よって(あ)〜(お)の解答は提示のとおり確定します。
誤りやすいポイント
- (あ)を「同じ公演」や「同じ席種」と書くと、行ロック競合の粒度が合わず減点。
- (う)を「購入フラグ」と誤解すると、UPDATE 条件式が自己矛盾になる。
- 早期コミットをロールバックの代わりに記述してしまうミス。
FAQ
Q: UPDATE 条件に「購入番号=NULL」を入れるだけで本当に競合を防げますか?
A: 行を UPDATE するときに専有ロックが取得されるため、他トランザクションは同一行更新を待機します。先着トランザクションが購入番号を設定し終えれば、後続トランザクションは WHERE 条件に合致せず 0 行更新になり即座に「購入できない」と判定できます。
A: 行を UPDATE するときに専有ロックが取得されるため、他トランザクションは同一行更新を待機します。先着トランザクションが購入番号を設定し終えれば、後続トランザクションは WHERE 条件に合致せず 0 行更新になり即座に「購入できない」と判定できます。
Q: 1座席ごとにコミットすると ACID の一貫性は保てますか?
A: 座席単位で在庫を完全に分割しているため、一括コミットにしなくても整合性は失われません。逆にコミット間隔短縮でロック競合時間を劇的に削減できます。
A: 座席単位で在庫を完全に分割しているため、一括コミットにしなくても整合性は失われません。逆にコミット間隔短縮でロック競合時間を劇的に削減できます。
Q: なぜ SELECT(確認)を省けるのですか?
A: UPDATE 条件に「購入番号=NULL」を埋め込めば、確認と状態遷移を同一 SQL で行えます。2ステップを1ステップに集約すると、READ→WRITE の間に状態が変わる「TOCTOU」問題も回避できます。
A: UPDATE 条件に「購入番号=NULL」を埋め込めば、確認と状態遷移を同一 SQL で行えます。2ステップを1ステップに集約すると、READ→WRITE の間に状態が変わる「TOCTOU」問題も回避できます。
関連キーワード: 排他制御、共有ロック、行レベルロック、トランザクション、コミット
設問2:〔オンラインチケット販売処理の設計〕 について(1)、(2)に答えよ。
(2)空席管理システムで実行するトランザクションの ISOLATION レベルはREAD COMMITTED(①)と REPEATABLE READ(②)のどちらを設定すべきか、①か②で答えよ。 また、その理由を30字以内で述べよ。
模範解答
ISOLATIONレベル:②
理由:同時実行した他者が同じ座席を仮予約できないようにするため
解説
解答の論理構成
- 目的の確認
空席確認~仮予約の間に「同時実行されたトランザクションのやり直しが極力発生しないようにする方針」(【問題文】)が示されています。 - READ COMMITTED の挙動
表1より、"READ COMMITTED" は「参照終了時に共有ロックを解放」。座席行を SELECT した直後にロックが外れるため、他の会員が直後に UPDATE で仮予約できてしまいます。 - REPEATABLE READ の挙動
同表より、"REPEATABLE READ" は「トランザクション終了時に解放」。SELECT した座席行は COMMIT まで共有ロックが維持され、他者による UPDATE(専有ロック要求)は待ち状態になります。 - 要件との対応
仮予約確定まで一貫性を保ちたい → "REPEATABLE READ" が適合。 - 30字以内の理由
「同時実行した他者が同じ座席を仮予約できないようにするため」。
誤りやすいポイント
- 「変更は専有ロック時のみ影響」と思い込み,SELECT だけなら READ COMMITTED で良いと判断してしまう。
- ロック粒度が「行単位」である点を見落とし、トランザクション全体に影響が大きいと誤解する。
- 座席行を UPDATE する③の段階だけを見て,SELECT 時の共有ロックが重要なことを忘れる。
FAQ
Q: READ COMMITTED でも③の UPDATE 前に専有ロックを掛ければ十分では?
A: ②の共有ロック維持が無いと、②~③の間に他トランザクションが UPDATE を行い競合が発生し、やり直しが増えます。
A: ②の共有ロック維持が無いと、②~③の間に他トランザクションが UPDATE を行い競合が発生し、やり直しが増えます。
Q: "SERIALIZABLE" を選ばない理由は?
A: 行ロックで十分に相互排他でき、必要以上のロック拡大や性能低下を避けられるため、本問題では "REPEATABLE READ" が最適解です。
A: 行ロックで十分に相互排他でき、必要以上のロック拡大や性能低下を避けられるため、本問題では "REPEATABLE READ" が最適解です。
Q: ロック待ちが長くなる懸念は?
A: (イ)「会員に不便」の指摘を受け、後続処理を1座席ずつ短いトランザクションに分割する対策が示されています。
A: (イ)「会員に不便」の指摘を受け、後続処理を1座席ずつ短いトランザクションに分割する対策が示されています。
関連キーワード: 共有ロック、排他制御、トランザクション分離、二重予約防止、行ロック
設問3:〔レプリケーションの設計〕 について、(1)〜(3)に答えよ。
(1)図 6 中の(ア)〜(ウ)に入れる適切な字句を、本文中の字句を用いて答えよ。(ア、イは順不同)
模範解答
ア:席種在庫
イ:座席状況
ウ:1か所のデータを複数か所に複製
解説
解答の論理構成
- レプリケーション対象テーブルの決定
- 空席表示に必要な情報は「席種ごとの空席数」と「座席ごとの空席/仮予約状態」。
- 問題文の定義
- 「席種在庫には、席種ごとの空席数をもつ。」
- 「座席状況には、公演開催明細ごとの全ての座席の状況をもつ。」
- よって(ア)(イ)にはこれら2テーブルを入れる。
- レプリケーション方式の選定
- 委託先は“サービスの提供先ごとにレプリカデータを用意する”ため、1つのオリジナルから複数のレプリカに配信する形になる。
- RDBMS仕様 2.(1) より「1か所のデータを複数か所に複製する機能」が該当。
- よって(ウ)は「1か所のデータを複数か所に複製」。
- 結合
- 以上より(ア)「席種在庫」、(イ)「座席状況」、(ウ)「1か所のデータを複数か所に複製」と決定します。
誤りやすいポイント
- 「公演開催明細」を対象に選んでしまう
→ 空席数自体を保持していないため目的外。 - (ウ)を「双方向に反映」と誤記
→ 委託先からオリジナルへは更新しないので双方向は不要。 - RDBMS仕様 2.(2) の“イベント型”と混同
→ 問われているのはデータ流方向であり同期方式ではない。
FAQ
Q: 席種在庫だけでは空席情報を表せませんか?
A: 仮予約中かどうかは「座席状況」にしか無いので両テーブルが必要です。
A: 仮予約中かどうかは「座席状況」にしか無いので両テーブルが必要です。
Q: なぜ双方向レプリケーションを採用しないのですか?
A: 委託先は閲覧専用で更新を行わない設計だからです。双方向にすると不要な衝突処理が増え、性能と整合性リスクが上がります。
A: 委託先は閲覧専用で更新を行わない設計だからです。双方向にすると不要な衝突処理が増え、性能と整合性リスクが上がります。
Q: イベント型/バッチ型のどちらを適用しますか?
A: 表3対策で「イベント型のレプリケーション機能を適用する」と明記されており、本問はデータ流方向のみを答えさせる設問です。
A: 表3対策で「イベント型のレプリケーション機能を適用する」と明記されており、本問はデータ流方向のみを答えさせる設問です。
関連キーワード: レプリケーション、排他制御、空席管理、一貫性、トランザクション
設問3:〔レプリケーションの設計〕 について、(1)〜(3)に答えよ。
(2)表3中の(エ)に入れる文章を、1. に倣って30字以内で述べよ。
模範解答
エ:キャンセルされた座席が空席として表示されない。
解説
解答の論理構成
- 【問題文】表3は“不正表示”の例を2つ列挙し、
- 「購入された座席が空席として表示される。」
- 「(エ)」
と対比構造で示しています。
- 指摘1は「販売済み ➔ 空席表示」という“売れたはずなのに○”矛盾。
- レプリケーション遅延で起き得るもう一方の矛盾は「キャンセルで空席に戻った ➔ ×(売切れ)表示」の逆パターン。
- したがって(エ)は「キャンセルされた座席が空席として表示されない。」となります。
- これにより表3の2項は、双方の遅延エラー(売れた/戻った)の両面を網羅し、レビューコメントと整合します。
誤りやすいポイント
- 「空席として表示される/されない」の主語を“購入”と“キャンセル”で取り違える。
- “取消”でなく“返金”など別語に置き換えてしまい原文引用要件を満たさない。
- 遅延原因を「排他制御」だと誤解し、解答をロック待ちの説明に寄せてしまう。
FAQ
Q: なぜ“キャンセル”に言及しないといけないのですか?
A: 指摘1が“購入”に関する不整合なので、対になる指摘2は“販売取り消し”に関する不整合を示すのが自然だからです。
A: 指摘1が“購入”に関する不整合なので、対になる指摘2は“販売取り消し”に関する不整合を示すのが自然だからです。
Q: 「空席として表示されない」と「売切れと表示される」はどちらが正しい?
A: どちらも意味は近いですが、原文の指摘1が「空席として表示される」と表現しているため、対応させて「空席として表示されない」が望ましいです。
A: どちらも意味は近いですが、原文の指摘1が「空席として表示される」と表現しているため、対応させて「空席として表示されない」が望ましいです。
関連キーワード: 非同期レプリケーション、データ不整合、トランザクション、ロック待ち
設問3:〔レプリケーションの設計〕 について、(1)〜(3)に答えよ。
(3)イベント型レプリケーション機能の対象とするテーブルとその列を答えて 表4を完成させよ。
なお、表4の欄は全て埋まるとは限らない。
模範解答

解説
解答の論理構成
- 表3のレビュー指摘
「レプリカデータにアクセスするタイミングによって…1. 購入された座席が空席として表示される。」
ここで問題となるのは公演・座席単位の可視性であり、空席管理システムの「空席フラグ」が実体です。 - レプリケーションの最小化方針
「レプリケーションの性能への影響を抑えるため、対象は必要最低限のものとする。」
よって列全体ではなく、購入表示に直接関わる列のみを選択します。 - 座席レベルの不整合解消
公演番号+公演日+開演時刻+座席番号で管理される「座席状況」テーブルには列「空席フラグ」があり、ON/OFFで可否を示します。イベント型で即時同期させれば購入直後に反映されます。 - 席種レベルの不整合解消
指摘2(表記は空欄(エ)だが内容は“売切れなのに空席として表示される/その逆”)は、席種単位の残量集計ずれが原因です。残量は「席種在庫」テーブルの「空席数」で一元管理されているため、同列を同期対象とします。 - 他の列が不要な理由
「仮予約フラグ」は購入確定前段階なので、レプリカ側の閲覧用途(確定情報のみ表示)には不要。その他列も同様に直接表示値に影響しません。
誤りやすいポイント
- 全行レプリケーションを選び、性能低下を招く。列単位選択が出来る仕様を見落とさないこと。
- 「仮予約フラグ」まで同期対象に入れてしまう。仮予約状態は閲覧サービスで公開すべき情報ではない。
- 「購入フラグ(チケット)」を選択してしまう。レプリカは空席管理システム側のテーブル構造と“同等”であり、販売管理システムの列は対象外です。
FAQ
Q: なぜ「座席状況」全列ではなく「空席フラグ」だけなのですか?
A: イベント型はトランザクションと同期するため、列数が多いほど通信量・ロック競合が増えます。問題文にある「性能への影響を抑えるため、対象は必要最低限」が優先されます。
A: イベント型はトランザクションと同期するため、列数が多いほど通信量・ロック競合が増えます。問題文にある「性能への影響を抑えるため、対象は必要最低限」が優先されます。
Q: 「席種在庫」の「空席数」だけで残席情報は十分ですか?
A: はい。席種在庫テーブルは公演+席種ごとに1行で空席数を保持しており、表示サービスは○/×判定か残席表示のみを行う前提です。他列(更新日時など)が無くても整合性は担保されます。
A: はい。席種在庫テーブルは公演+席種ごとに1行で空席数を保持しており、表示サービスは○/×判定か残席表示のみを行う前提です。他列(更新日時など)が無くても整合性は担保されます。
関連キーワード: イベント型レプリケーション、排他制御、空席フラグ、空席数、同期更新


