データベーススペシャリスト試験 2017年 午後102


トランザクションの排他制御に関する次の記述を読んで, 設問1〜3に答えよ。

 Y社は, オフィスじゅう器メーカである。 現在, 在庫管理システムのアプリケーションプログラム (以下, AP という) の改修を実施している。  
〔在庫管理システムのテーブル〕  在庫管理システムの主なテーブル構造を,図1に示す。 各テーブルには主索引が定義されている。
データベーススペシャリスト試験(平成29年 午後I 問2 図1)
〔在庫管理業務の概要〕 (1) 各地の生産拠点には,組立工場と,これに隣接する倉庫がそれぞれ一つ配置されている。 (2) 倉庫からの部品の出庫には, 倉庫から隣接する組立工場に出庫する場合と,倉庫から他の生産拠点の倉庫に出庫する場合がある。 (3) 倉庫は,倉庫コードで一意に識別され,組立工場は,工場コードで一意に識別される。 生産拠点を識別するコードは存在しない。 (4) 定期便は, 倉庫間で部品を配送する便であり,便番号で一意に識別される。 (5) 部品は,部品番号で一意に識別される。 (6) 部品の在庫は, 倉庫と部品の組合せで,その数量をもつ。 倉庫内に存在する在庫を,倉庫内在庫と呼ぶ。 このうち, 隣接する組立工場又は他の生産拠点の倉庫に向けて出庫対象となったものを, 出庫対象在庫と呼ぶ。 (7) 出庫要求とは,倉庫に対して部品の出庫を要求することである。 “出庫” テーブルに出庫要求の内容が登録され, 処理状況に ‘要求発生' が記録される。 出庫番号は,出庫要求の発生順の一意な連番である。 組立工場が出庫要求する場合, 出庫先倉庫コード及び出庫便番号の値は NULL となり, 出庫先工場コードが記録される。他の生産拠点の倉庫が出庫要求する場合, 出庫先工場コードは NULL となり,出庫先倉庫コードが記録され, 出庫便番号には該当する定期便の便番号が記録される。 (8) 在庫引当とは, 出庫要求に応じて倉庫内の在庫を引き当てることである。 在庫引当 AP は,毎日の業務中に定期的に実行され, その時点で登録されている出庫要求を処理する。 指定された倉庫コード, 部品番号, 出庫数量の出庫が可能かどうかチェックし、出庫可能であれば出庫対象在庫数量を更新する。 在庫引当が完了したら,処理状況は ‘引当実施' に更新される。 (9) 出庫とは, 出庫要求に従って, 倉庫から部品を出すことである。 出庫は多頻度で行われるので, 出庫ごとに在庫は更新されず, 出庫確定 AP でまとめて更新される。 (10) 出庫確定 AP は、 毎日の業務終了時に実行される。 “出庫” テーブルの処理状況が ‘引当実施' のものを対象に, 倉庫内在庫数量及び出庫対象在庫数量が更新され,処理が完了したら, 処理状況は ‘出庫実施’に更新される。 (11) 入庫とは,他の生産拠点の倉庫で出庫された部品を倉庫に入れることである。入庫による在庫の更新は,在庫引当 AP 及び出庫確定 AP と同時に実行されることはない。  
〔RDBMS の排他制御〕 (1) 在庫管理システムの RDBMS で選択できるトランザクションの ISOLATION レベルとその排他制御は,表1のとおりである。  ロックは行単位で掛ける。 共有ロックが掛かっている間, 他のトランザクションからの対象行の参照は可能であり,更新は共有ロックの解放待ちとなる。 専有ロックが掛かっている間, 他のトランザクションからの対象行の参照, 更新は専有ロックの解放待ちとなる。
データベーススペシャリスト試験(平成29年 午後I 問2 表1)
(2) 索引を使わずに, テーブルスキャンで全ての行に順次アクセスする場合, 検索条件に合致するか否かにかかわらず全行がロック対象となる。 索引スキャンの場合,索引から読み込んだ行だけがロック対象となる。  
〔分析機能の追加〕  適切な生産計画を立てるために, 部品ごとに在庫数量, 出庫数量の日別の推移状況を見たいという要望があり,そのための集計 AP を追加した。 集計 AP で実行するSQL の一部を, 表2に示す。 SQL1 は各部品の出庫年月日ごとの出庫数量を集計する。  また, SQL1 では、 出庫が全くない部品も集計対象とする。 SQL2 は, 各部品の倉庫間の出庫について, 出庫年月日,出庫元倉庫, 出庫先倉庫ごとに出庫数量を集計する。表2 集計 AP で実行する SQL の構文 (未完成)
データベーススペシャリスト試験(平成29年 午後I 問2 表2)
〔在庫引当 AP の改修〕  在庫管理システムでは, トランザクションの ISOLATION レベルを REPEATABLEREAD として設計, 運用していた。 システムの改修に当たり,在庫引当 AP のトランザクションの ISOLATION レベルを READ COMMITTED に変更することにした。ISOLATION レベルの変更で問題が発生しないように在庫引当AP を改修した。  改修前の在庫引当 AP は図 2, 改修後の在庫引当AP は図3のとおりである。 これらの AP の実行に先立って, “出庫” テーブルの処理状況が ‘要求発生' の行を抽出し、出庫先倉庫ごとに分割したファイルを作成する。 それぞれのファイルのレコードは,出庫番号順に記録されている。 作成したファイルを入力として, 在庫引当 AP を並列実行している。 在庫引当 AP は, 入力ファイルのレコードごとに繰り返し実行される。  なお,図 2,3中のホスト変数 hv0 は出庫番号, hv1 は出庫元倉庫コード, hv2 は部品番号, hv3 は出庫数量を表す。 hv4 と hv5 は, 検索結果を返す出力ホスト変数を表す。
データベーススペシャリスト試験(平成29年 午後I 問2 図2)
データベーススペシャリスト試験(平成29年 午後I 問2 図3)   〔出庫確定 APの改修 〕  出庫確定 AP の処理に掛かる時間を短縮するために, 出庫確定 AP を並列に多重プロセスで実行するように変更することにした。 “出庫” テーブルの出庫番号の値の範囲指定で各プロセスに均等に配分して, REPEATABLE READ で並列実行する。 出庫確定 AP の概要は,図4のとおりである。
データベーススペシャリスト試験(平成29年 午後I 問2 図4)

設問1

〔分析機能の追加〕について,表 2 中の(a)〜(e)に入れる適切な字句を答えよ。
模範解答
a:SUM(S.出庫数量) b:LEFT OUTER JOIN c:GROUP BY B.部品番号,S.出庫年月日 d:出庫便番号 e:NOT NULL
解説

キーワードと論点整理

本問では、分析用 SQL(SQL1, SQL2)における次の論点を押さえる必要があります。
ブランク解答論点
(a)SUM(S.出庫数量)出庫数量を日付ごとに集計するための集約関数
(b)LEFT OUTER JOIN出庫が全くない部品も含める結合
(c)GROUP BY B.部品番号,S.出庫年月日部品番号・出庫年月日で集計後に並べ替え
(d)出庫便番号倉庫間出庫を判定するカラム
(e)NOT NULL倉庫間出庫を「出庫便番号が NULL でない」行に限定

解答の論理的説明

SQL1 のポイント

問題文中に「SQL1 では、出庫が全くない部品も集計対象とする。」とあります。
これを実現するには、主テーブルを「部品ごとの在庫」を持つ 在庫(エイリアス B)とし、そこに出庫テーブル 出庫(エイリアス S)を結合します。
結合方法として、出庫が存在しない部品も残すには LEFT OUTER JOIN が必要です。
さらに「各部品の出庫年月日ごとの出庫数量を集計する」ため、SUM 関数で数量を加算します。
  1. (a) 出庫数量の集計
    「各部品の出庫年月日ごとの出庫数量を集計する」 → SUM(S.出庫数量)
  2. (b) 結合の種類
    「出庫が全くない部品も集計対象とする。」 → LEFT OUTER JOIN
  3. (c) 集計後のグルーピング
    GROUP BY は「B.部品番号,S.出庫年月日」でグループ化する必要があります。
以上より、SQL1 は次のようになります(主要部分のみ抜粋)。
SELECT
  B.部品番号,
  S.出庫年月日,
  SUM(S.出庫数量)                 -- (a)
FROM
  在庫 AS B
  LEFT OUTER JOIN                -- (b)
  出庫 AS S
    ON B.倉庫コード = S.出庫元倉庫コード
   AND B.部品番号   = S.部品番号
   AND S.出庫年月日 >= '2016-04-01'
   AND S.出庫年月日 <  '2017-04-01'
GROUP BY                          -- (c)
  B.部品番号,
  S.出庫年月日;

SQL2 のポイント

SQL2 は「各部品の倉庫間の出庫について、出庫年月日, 出庫元倉庫, 出庫先倉庫ごとに出庫数量を集計する」ものです。
問題文より:
「倉庫から他の生産拠点の倉庫に出庫する場合は…出庫便番号には該当する定期便の便番号が記録される。」
「組立工場が出庫要求する場合…出庫便番号の値は NULL となり…」
よって 定期便による倉庫間出庫だけを対象とする には、出庫便番号が NULL でない行を選べばよいです。
  1. (d) 対象カラム → 出庫便番号
  2. (e) NULL 判定 → NOT NULL
SELECT
  部品番号,
  出庫年月日,
  出庫元倉庫コード,
  出庫先倉庫コード,
  SUM(出庫数量)
FROM
  出庫
WHERE
  出庫便番号 IS NOT NULL      -- (d),(e)
  AND 出庫年月日 >= '2016-04-01'
  AND 出庫年月日 <  '2017-04-01'
GROUP BY
  部品番号,
  出庫年月日,
  出庫元倉庫コード,
  出庫先倉庫コード;

受験者が誤りやすいポイント

  • INNER JOIN と LEFT OUTER JOIN の混同
    出庫がない部品を含めたい場合、INNER JOIN では行が落ちてしまうので必ず LEFT OUTER JOIN を用いる点に注意。
  • WHERE によるフィルタリング位置
    LEFT OUTER JOIN 後に WHERE 句で結合先テーブルのカラムに対して条件を付けると、NULL の行を排除してしまい、LEFT JOIN の意味が損なわれる場合がある。
    → 本問 SQL1 では、日付条件を ON 句内に置くことで、NULL 行を残したままフィルタリングしている。
  • NULL 判定の書き方
    IS NULLIS NOT NULL は比較演算子 =<> ではなく専用の構文を用いる。

試験対策として覚えておくべきポイント

  1. SQL の結合で「左側のテーブルを必ず残す」には LEFT OUTER JOIN
  2. 集計関数を使う場合、SUM(...)GROUP BY の組み合わせ
  3. NULL 判定は IS NULLIS NOT NULL
  4. JOIN の ON 節と WHERE 節の使い分け:フィルタリングのタイミングが異なる
  5. 検索条件に日付範囲を指定するときは、>= '開始日' AND < '終了日' のパターンが多い
これらを整理しておけば、類題にも対応可能です。

設問2(1)〔在庫引当 AP の改修〕について,(1)〜(3)に答えよ。

図2の改修前の在庫引当 AP が, REPEATABLE READ で複数同時に実行されるとデッドロックが発生するおそれがある。 どのような場合にデッドロックが発生するか, AP 間の SQL の実行状況を、 図2中の丸数字を用いて 60字以内で述べよ。
模範解答
“在庫”テーブルの同じ行に対して,先行するAPの①と②の間で,後続のAPの①が実行された場合
解説

キーワード・論点整理

  • デッドロック
  • トランザクションの ISOLATION レベル:REPEATABLE READ
  • 図2 中の丸数字①(SELECT 文での共有ロック取得)と②(UPDATE 文での専有ロック取得)
  • 同一行に対するロック取得の順序競合

解答の論理的説明

REPEATABLE READ では,【RDBMS の排他制御】の記述にあるように
「データ参照時に共有ロックを掛け,トランザクション終了時に解放する。
データ更新時に専有ロックを掛け,トランザクション終了時に解放する。」
という動作になります。
図2 の処理手順を踏まえると、以下のように2つの在庫引当AP(以降AP1、AP2)が同じ在庫行を対象に同時実行されるとき、デッドロックが発生します。
  1. AP1 が丸数字①の SELECT … FROM 在庫 を実行
    → 対象行に共有ロックを取得
  2. AP2 が丸数字①の SELECT … FROM 在庫 を実行
    → 対象行に共有ロックを取得
  3. AP1 が丸数字②の UPDATE 在庫 … を実行しようとし、
    → 共有ロックから専有ロックへのアップグレードを要求し待機
  4. AP2 も丸数字②の UPDATE 在庫 … を実行しようとし、
    → 同じく待機
この状態でAP1はAP2の共有ロック解除を待ち、AP2はAP1の共有ロック解除を待つため、互いにロックを獲得できずデッドロックに陥ります。
したがって、**「在庫テーブルの同じ行に対して,先行するAPの①と②の間で,後続のAPの①が実行された場合」**にデッドロックが発生します。

注意すべきポイント

  • REPEATABLE READ では SELECT 時の共有ロックが トランザクション終了時 まで保持される点を押さえる。
    • READ COMMITTED では共有ロックは 参照終了時 に解放されるため、本事象は発生しない。
  • ロックの「共有(=読取り)」と「専有(=更新)」の性質を混同しない。
  • 同一行に対して複数トランザクションが共有ロックを取得し、かつその後でそれぞれ専有ロックを要求するとデッドロックになる。

覚えておきたい知識

  • トランザクション分離レベルによるロックの取得・解放タイミング
    分離レベルSELECT(参照)時のロックUPDATE(更新)時のロック
    READ COMMITTED共有ロック/参照終了時解放専有ロック/トランザクション終了時解放
    REPEATABLE READ共有ロック/トランザクション終了時解放専有ロック/トランザクション終了時解放
  • デッドロック回避策の例
    • 同一トランザクション内でロック順序を統一する
    • 悲観的ロックから楽観的ロックへの切替検討
    • ロックタイムアウトやデッドロック検出機能の活用
以上を理解し、複数プロセスが同一行を同時に更新しようとする場合のロック競合とデッドロックを正しく把握してください。

設問2(2)〔在庫引当 AP の改修〕について,(1)〜(3)に答えよ。

図2の改修前の在庫引当 AP が, READ COMMITTED で同じ倉庫の同じ部品に対して複数同時に実行されると, 在庫数量が不正になるおそれがある。 在庫数量が不正になる AP の実行状況を図5に示す。 不正になるのは, AP2 の①〜④の各SQL が, t2, t4, t6, t8 のどの時間帯で実行された場合か, 該当する時間帯に①〜④を記入せよ。 ここで,一つの時間帯に複数の SQL を実行できる。  また,この状況が発生した場合の, 在庫数量が不正とは具体的にどのような状態か, 30字以内で述べよ。 データベーススペシャリスト試験(平成29年 午後I 問2 図5)
模範解答
実行状況: データベーススペシャリスト試験(平成29年 午後I 問2 設問2-2)
状態:出庫対象在庫数量が倉庫内在庫数量を超える。
解説

1. キーワード・論点の整理

  • ISOLATION レベル
    • READ COMMITTED:
      「データ参照時に共有ロックを掛け,参照終了時に解放する。データ更新時に専有ロックを掛け,トランザクション終了時に解放する。」
    • REPEATABLE READ:
      「データ参照時に共有ロックを掛け,トランザクション終了時に解放する。データ更新時に専有ロックを掛け,トランザクション終了時に解放する。」
  • SELECT と共有ロックの保持期間
    • READ COMMITTED では SELECT ステートメントが終わると共有ロックを解放 → 他トランザクションの UPDATE を間に挟める
    • REPEATABLE READ ではトランザクション終了まで共有ロックを保持 → 後続の SELECT は更新済みデータを見る
  • Lost Update(ロスト・アップデート)
    ‥複数トランザクションが同じ行を同じ値を基に更新し,後からコミットしたほうが前の更新を上書きしてしまう現象
  • 図2(改修前在庫引当 AP)の処理
    ① SELECT 倉庫内在庫数量, 出庫対象在庫数量 INTO :hv4, :hv5
    ② UPDATE 在庫 SET 出庫対象在庫数量 = 出庫対象在庫数量 + :hv3
    ③ UPDATE 出庫 SET 処理状況 = ’引当実施’
    ④ COMMIT

2. なぜその実行順序になるのか

  1. READ COMMITTED の場合、①の SELECT が終了すると共有ロックが解放されます。
  2. 他のプロセス(AP1)が①→②→③→④を完了してコミットしても、その間に別プロセス(AP2)の①が先に実行できてしまいます。
  3. AP2 は古い :hv4(倉庫内在庫数量) と :hv5(出庫対象在庫数量) を使って「在庫引当可能」と判断し、後で②③④を実行すると Lost Update が発生します。
  4. 結果として「出庫対象在庫数量」が不正に加算され(または下回り)、最終的に「出庫対象在庫数量が倉庫内在庫数量を超える」 という整合性違反が発生します。

実行状況(AP2 の SQL が問題となるタイミング)

t2t4t6t8
②③④
または
t2t4t6t8
①②③④
  • t2 で ①(SELECT) を実行(共有ロックはステートメント終了時に解放)
  • AP1 が t4, t6 に②③④を完了・コミット
  • t8 で AP2 の ②③④(UPDATE→UPDATE→COMMIT)を実行 → Lost Update

3. 受験者が誤りやすいポイント

  • トランザクション分離レベルの共有ロック期間
    「SELECT を実行すると必ず次の UPDATE をブロックする」と思い込むと誤解します。
  • FOR UPDATE の有無
    図3 改修後では SELECT … FOR UPDATE によって行ロックを保持するため、READ COMMITTED でも競合を防げます。
  • 索引スキャン vs テーブルスキャン
    索引スキャンなら対象行のみロック、テーブルスキャンでは全行ロックになる点を区別していないことがある。

4. 試験対策として覚えておくべきポイント

項目内容
ISOLATION レベル各レベルごとのロック取得と解放のタイミングを正確に理解する
共有ロック/専有ロックSELECT と UPDATE で取得するロックの種類と保持期間
Lost Update同じデータを複数 TX が同じ前提値で更新 → 後のコミットで前を上書き
SELECT … FOR UPDATE共有ロックではなく専有ロックを即時に取得 → 更新前に他を排他
インデックスの利用索引スキャンだと該当行のみ、スキャンだと全行がロック対象になる
これらを整理しておくことで,排他制御の問題で安定した答案を作成できます。

設問2(3)〔在庫引当 AP の改修〕について,(1)〜(3)に答えよ。

図3中の(f)に入れる適切な字句を答えよ。
模範解答
f:CURRENT
解説

解答のキーワードと論点整理

  • キーワード:CURRENT OF
  • 論点:
    1. 図3で「DECLARE 在庫カーソル CURSOR … FOR UPDATE」とし、カーソル取得行を専有ロックする点
    2. 更新対象の行を特定するためにSQL標準で用いられる句が「WHERE CURRENT OF カーソル名」である点

なぜ「CURRENT」が正解なのか

図3の該当箇所は以下のように示されています(太字は引用箇所)。
…  
UPDATE 在庫 SET 出庫対象在庫数量 = 出庫対象在庫数量 + :hv3  
    WHERE □f OF 在庫カーソル  
…  
  1. 図3では、最初に
    DECLARE 在庫カーソル CURSOR
    FOR SELECT … FROM 在庫 … FOR UPDATE
    OPEN 在庫カーソル
    FETCH 在庫カーソル INTO :hv4, :hv5
    とあり、FOR UPDATE 指定でカーソルが取得する行に専有ロックが掛かります。
  2. 取得済みの行に対して更新を行うには、SQL標準で
    「WHERE CURRENT OF カーソル名」
    という文法を用い、カーソルが現在参照している行を指定します。
  3. したがって、□f に入るべき字句は CURRENT です。
    完成するSQLは次のとおりです。
    UPDATE 在庫
      SET 出庫対象在庫数量 = 出庫対象在庫数量 + :hv3
      WHERE CURRENT OF 在庫カーソル
    

受験者が誤りやすいポイント

誤りやすい語句誤りの理由
WHERE OFOF は含まれるが、主語の部分がなく非文法的
WHERE POSITION OF
カーソル名
POSITION句はSQL標準に存在しない
WHERE CURRENTCURRENT は正しいが、OF句を忘れてしまう
WHERE CURSOR OF
在庫カーソル
CURSOR キーワードは使わず、CURRENT 固有の句である
  • 「CURSOR」や「FETCH」と混同してしまうと、WHERE CURSOR OF のような誤答につながります。
  • 「WHERE CURRENT」だけでは WHERE CURRENT OF … という決まり書式を満たしません。

試験対策として覚えておくべきポイント

  1. カーソルを使った更新
    • DECLARE カーソル名 CURSOR FOR SELECT … FOR UPDATE
    • OPENFETCHUPDATE … WHERE CURRENT OF カーソル名CLOSE
    • 最後に COMMIT でトランザクション終了
  2. FOR UPDATE 指定
    • カーソル取得時に対象行に専有ロックを掛ける
    • 取得行に対して後から WHERE CURRENT OF で安全に更新
  3. SQL標準の句の正確な使い方
    • WHERE CURRENT OF はセットで使う
    • 他のキーワード(POSITION、CURSORなど)は更新句には用いない
これらを正確に理解し、図3の未完成箇所には必ず CURRENT を埋めることが必要です。

設問3(1)〔出庫確定 AP の改修〕について(1),(2)に答えよ。

並列に実行するように変更したが, スループットはさほど向上しなかった。ボトルネックはどこにあるかを説明する次の記述について,(ア)〜(エ) に入れる適切な字句を答えよ。  複数の出庫を並列に処理することになるが, 同じ(ア)と(イ)に対する出庫が複数存在するので, “(ウ)”テーブルの更新で(エ)が発生する。 (ア、イは順不同)
模範解答
ア:倉庫コード イ:部品番号 ウ:在庫 エ:ロックの解放待ち
解説

模範解答のキーワードと論点整理

本問では並列実行時のロック競合に着目します。特に以下の4つがキーワードです。
キーワード説明
倉庫コード同一の倉庫単位で在庫行が識別されるプライマリキーの一部
部品番号同一の部品単位で在庫行が識別されるプライマリキーの一部
在庫倉庫ごと・部品ごとの在庫数量を管理するテーブル名
ロックの解放待ち他トランザクションの専有ロック解除を待機する状態

解答の論理的説明

  1. 問題文が指すボトルネックの説明
    「複数の出庫を並列に処理することになるが, 同じ(ア)と(イ)に対する出庫が複数存在するので, “(ウ)”テーブルの更新で(エ)が発生する。」
  2. なぜ「倉庫コード」「部品番号」か
    • 在庫テーブルは「倉庫コード, 部品番号」を主キーとして在庫行を一意に管理します(問題文「在庫テーブルの主キー」)。
    • 並列プロセスは出庫単位で同じ倉庫・同じ部品を更新する可能性があるため、同一行に対して複数の専有ロック要求が発生します。
  3. なぜ「在庫」テーブルか
    • 図4の処理手順 2-1, 2-2 にあるように、各出庫プロセスは
      「“在庫”テーブルの倉庫内在庫数量を更新(出庫数量分を減算)」
      「“在庫”テーブルの出庫対象在庫数量を更新(出庫数量分を減算)」
      を行います。
    • この更新時に行単位の専有ロックが掛かります(問題文「ロックは行単位で掛ける。専有ロックが掛かっている間…更新は専有ロックの解放待ちとなる。」)。
  4. なぜ「ロックの解放待ち」か
    • 同一行に対して複数のトランザクションが同時に更新を試みると、先に取得した専有ロックが解放されるまで後続は待機します。
    • 結果として、更新処理間でロックのコンテンションが発生し、スループットが頭打ちになります。
以上より,空欄には次の語句が適切です。
倉庫コード部品番号在庫ロックの解放待ち

受験者が誤りやすいポイント

  1. 出庫テーブルを選んでしまう
    • 出庫確定APは「出庫」テーブルを更新しますが,出庫番号の範囲を分割して並列処理しているため,出庫テーブル上ではプロセス間で競合しません。
    • 真の競合は,複数プロセスが同じ在庫行を更新する「在庫」テーブルで起きます。
  2. テーブルロックと行ロックの違い
    • 問題文では「ロックは行単位で掛ける」と明示されています。テーブルロックではなく行ロックであることを押さえておきましょう。
  3. ISOLATIONレベルの影響
    • ISOLATIONレベルが REPEATABLE READ でも READ COMMITTED でも,更新時の専有ロック待機は発生します。ロックの持続期間に違いはありますが,競合自体は同様に起きます。

試験対策として押さえておくべきポイント

  • RDBMSの排他制御
    • 行単位ロックとテーブル単位ロック,共有ロック/専有ロックの動作を正確に理解する。
    • ISOLATIONレベル(READ COMMITTED/REPEATABLE READ)ごとのロック取得・解放タイミングを整理する。
  • スケーラビリティ設計
    • 並列処理時の「ホットスポット」(同一行への更新集中)はボトルネックになりやすい。
    • パーティション分割や負荷分散をどこに適用するか,テーブル設計と業務単位の粒度を検討する。
  • 試験問題の読み方
    • 「同じ○○に対する更新がある」という記述は,そのリソースに競合が生じることを示唆しています。
    • 図や手順だけでなく,選択しているISOLATIONレベルやロック方式の記述も併せて確認しましょう。

設問3(2)〔出庫確定 AP の改修〕について(1),(2)に答えよ。

(1)のボトルネックを解消するためには出庫確定 AP をどのように変更する必要があるかを説明する次の記述について,(オ)〜(ケ)に入れる適切な字句を答えよ。  出庫番号ではなく,(オ)と(カ)の組合せの値の範囲指定で各プロセスに配分するように変更する。 また, 図4の1で, 出庫番号の昇順ではなく,(オ)と(カ)の昇順に処理を行うように変更する。 “(キ)”テーブルの“(オ)”列と“(カ)”列に,複数列索引を定義しておく。  なお,この索引を定義していない場合, 自プロセスの対象行かを判定するための参照が(ク)となるので,他プロセスが(ケ)した行を参照しようとしてロックの解放待ちとなり, 別のボトルネックが生じる。(オ、カは順不同)
模範解答
オ:出庫元倉庫コード カ:部品番号 キ:出庫 ク:テーブルスキャン ケ:更新 又は 専有ロック
解説

キーワード・論点整理

  • 並列プロセス実行のボトルネック
    出庫確定 AP を複数プロセスで並列実行するときに、各プロセスが同じ「出庫番号」の範囲を基準にするとロック競合が起こりやすい。
  • 複数列索引(複合インデックス)
    複数の列を組み合わせた索引を定義すると、索引スキャンで対象行のロックを限定でき、排他ロックの待ちを減らす。
  • テーブルスキャン vs 索引スキャン
    • テーブルスキャン:全行にロックを掛ける → ロック競合増
    • 索引スキャン:該当行のみロック → 並列実行に有利

解答選択の論理的根拠

設問文の該当箇所を引用します。
「出庫番号ではなく,(オ)と(カ)の組合せの値の範囲指定で各プロセスに配分するように変更する。また,図4の1で,出庫番号の昇順ではなく,(オ)と(カ)の昇順に処理を行うように変更する。 “(キ)”テーブルの“(オ)”列と“(カ)”列に,複数列索引を定義しておく。なお,この索引を定義していない場合,自プロセスの対象行かを判定するための参照が(ク)となるので,他プロセスが(ケ)した行を参照しようとしてロックの解放待ちとなり,別のボトルネックが生じる。」
  1. 各プロセスに割り当てる範囲キー
    • 出庫番号ではなく、出庫元倉庫コード部品番号の組合せで範囲分割
      → 「(オ)=出庫元倉庫コード」「(カ)=部品番号」
  2. 処理順序の変更
    • 出庫番号昇順ではなく、同じく出庫元倉庫コード → 部品番号の昇順で処理
      → テーブル全体を均等に分散して負荷集中を防ぐ
  3. 複数列索引の定義場所
    • “(キ)”テーブル=出庫テーブルに対して、
    • 複合索引:(出庫元倉庫コード, 部品番号)
      を定義しておく
  4. 索引未定義時の問題
    • 自プロセスの対象行かを判定する参照が テーブルスキャン になる
    • テーブルスキャンでは全行をロックし、他プロセスが持つ更新/専有ロックを解放待ち
      → 新たなボトルネックが発生

誤りやすいポイント

  1. 「(オ)」「(カ)」に別の組合せを考えてしまう
    • 出庫先倉庫コード出庫便番号では範囲分割とソートに適さない
    • 処理対象を均等に分割できるキーであることが重要
  2. 「(ク)」を「索引スキャン」と書いてしまう
    • 索引が未定義のため、判定処理はテーブル全行走査=テーブルスキャンになる
  3. 「(ケ)」を「共有ロック」と書いてしまう
    • 他プロセスが実行中の UPDATE で掛かるのは専有ロック(更新ロック)

試験対策ポイント

  • 並列実行時の分散キー設計
    並列プロセスに同一範囲で集中しないよう、複数の列を組み合わせたキーで範囲分割・処理順序を決める。
  • 複合インデックスの効果
    複数列索引を定義すると、索引スキャンで対象行のみロックでき、テーブルスキャンに伴う不要なロックを防止できる。
  • 排他制御とロック挙動
    • テーブルスキャン:全行にロック → 他トランザクションの待ち増
    • 索引スキャン:該当行のみロック
    • 共有ロック/専有ロックの違いを正確に理解すること
  • SQL実行計画の基礎知識
    特定のWHERE句で索引が使われないときはテーブルスキャンになること、並列実行の排他制御への影響を抑える工夫を覚えておきましょう。
← 前の問題へ次の問題へ →

©︎2025 情報処理技術者試験対策アプリ