DBデータベーススペシャリスト試験 午後Ⅰ
平成29年度春期 データベーススペシャリスト 午後Ⅰ 問2
事例を読んで設問の答えを考えてから、解説のポイントとIPA公式の解答例・採点講評で確認しましょう。
問題




![図3 READ COMMITTED で実行する改修後の在庫引当 AP(未完成)。FOR UPDATE指定の在庫カーソルをDECLARE・OPEN・FETCHし,出庫可否を判定する。在庫をWHERE[f]OF 在庫カーソルでUPDATEし,CLOSE後に出庫の処理状況を更新してCOMMITする。専有ロックに関する注記付き。](/figures/cc2f401588b159064c50aec1b1e4ca41c08d78785e60c13fe180e3d58a03d1ca.webp)


解き方のヒントを見る
処理の時系列から並行性の影響を考える
複数の処理が同時に動く場面では、それぞれがどのデータをどの時点で読み書きするかを順序立てて並べることが検討の出発点になります。変更前後で何が変わり得るかを、処理の重なり方に注目して自分の言葉で整理してみましょう。
この問題で問われていること
問われているのは、設定や実行形態を変えたときに、同時に動く処理どうしの間でデータの見え方や更新結果にどのような影響が生じ得るかを、根拠を持って説明できるかどうかという点だと考えられます。
視点
並行実行の課題を検討するときは、個々の処理を単独で見るのではなく、複数の処理の読み取りと書き込みを一本の時間軸の上に並べてみると整理しやすくなります。互いの操作がどの順で重なり得るかを書き出したうえで、その重なりが最終的なデータの値や集計の結果にどう反映されるかを、一つずつ自分で追ってみてください。
確認ポイント
- 各処理がデータを読む時点と書く時点を、時間の順に書き出せているか
- 二つ以上の処理の操作が重なる区間で、相手の変更が見えるかどうかを自分で確かめたか
- その重なりが最終的な値や集計結果にどう表れるかを、具体的な例で追えたか
正解と解説を見る
解説
在庫管理システムを題材に、外結合とGROUP BYを使った集計SQL、REPEATABLE READで同じ行を対象に起きるデッドロック、READ COMMITTEDで起きる更新の不整合とFOR UPDATEカーソルによる対策、並列化した出庫確定APのロック待ちの原因と解消策を問う問題です。表1のロック保持期間と、〔RDBMSの排他制御〕(2)の「テーブルスキャンでは全行がロック対象になる」という規則を当てはめれば、各設問の答えを導けます。
問題の全体像
Y社の在庫管理システムのAP改修が題材です。在庫引当APは出庫要求ごとに、“在庫”行を参照して出庫できるかを判定し、出庫対象在庫数量に加算します。出庫確定APは業務の終了時に、倉庫内在庫数量と出庫対象在庫数量をまとめて減算します。出題趣旨では、同時に実行されるAP同士が影響し合って予期しない結果を生まないように、SQLの設計能力とトランザクション制御・排他制御の理解を問うとしています。採点講評によると、全体の正答率は低めでした。設問1(SQL)の正答率は高かった一方、設問2(同じ行を対象にしたデッドロックと不整合)の正答率は低く、設問3では(1)エと(2)クの正答率が低かったとされています。
設問1(a)
SQL1は「各部品の出庫年月日ごとの出庫数量を集計する」ものです。SELECT句には部品番号と出庫年月日に続けて集計値を書く必要があります。“出庫”表の別名はSなので、公式解答例ではSUM(S.出庫数量)としています。
設問1(b)
SQL1には「出庫が全くない部品も集計対象とする」という条件があります。“在庫”(B)を基準にして、対応する“出庫”の行がない場合もBの行を残す必要があるので、公式解答例はLEFT OUTER JOINです。出庫年月日の範囲条件がWHERE句ではなくON句に書かれているのも、外結合で残した行を消さないためです。
設問1(c)
集計の単位は部品と出庫年月日なので、GROUP BY句が必要です。外結合で出庫がない部品のS側の列はNULLになるため、部品番号は必ず値を持つB側の列を使います。公式解答例はGROUP BY B.部品番号、 S.出庫年月日です。“在庫”は倉庫と部品の組合せで1行なので、部品番号でまとめると倉庫をまたいで集計されます。
設問1(d)
SQL2は倉庫間の出庫だけを対象にします。業務の概要(7)によると、他の生産拠点の倉庫への出庫では出庫便番号に定期便の便番号が記録され、組立工場への出庫では出庫便番号がNULLになります。この値の有無で倉庫間の出庫を区別できるので、公式解答例では出庫便番号としています。採点講評では、dの列名を誤った解答が散見されたと指摘されています。
設問1(e)
倉庫間の出庫では出庫便番号に値が入るので、条件は「出庫便番号 IS NOT NULL」となり、公式解答例はNOT NULLです。採点講評では、dの列名とeのNULL/NOT NULLの組合せを誤った解答が散見されたとあります。どの列が、どちらの出庫で値を持つのかを状況記述で確認することが大切です。
設問2(1)
REPEATABLE READでは、①のSELECTで掛けた共有ロックをCOMMITまで保持します。入力ファイルは出庫先倉庫ごとに分かれているので、別々のAPが同じ出庫元倉庫・同じ部品の“在庫”行を扱うことがあります。先行するAPが①を実行してから②を実行するまでの間に、後続のAPが同じ行に①を実行すると、両方が共有ロックを持った状態になります。その後、それぞれが②のUPDATEで専有ロックを取ろうとすると、互いに相手の共有ロックの解放を待つことになり、デッドロックが発生します。公式解答例は「“在庫”テーブルの同じ行に対して、先行するAPの①と②の間で、後続のAPの①が実行された場合」です。60字以内の答案では、同じ行であること、先行APの①と②の間、後続APの①の実行、の3つの要素を押さえます。採点講評では、複数のテーブルや行を対象にしたデッドロックの一般論を書いただけの誤答が目立ったとされています。
設問2(2)実行状況
READ COMMITTEDでは、①の共有ロックは参照が終わると解放されます。AP1の②(t3)で掛かる専有ロックは、④(t7)のCOMMITまで保持されます。不整合になるのは、AP2の①がAP1の②より前の値を読んだ場合です。つまりAP2の①はt2で実行されます。AP2の②をt4やt6に置くと、AP1の専有ロックの解放を待つことになり、その時間帯には実行できません。そのため②③④はt8になります。また、t2の中で①②③④をすべて実行してCOMMITまで終える場合も、AP1はt1で読んだ古い値を基に②を実行するので不整合になります。公式解答例では「t2に①、t8に②③④」または「t2に①②③④」の2通りを示しています。
設問2(2)状態
AP1とAP2は、どちらも更新前の同じ値(倉庫内在庫数量−出庫対象在庫数量)を見て出庫可能と判断し、それぞれの出庫数量を出庫対象在庫数量に加算します。その結果、実際の在庫を超えて引き当てられることがあります。公式解答例は「出庫対象在庫数量が倉庫内在庫数量を超える。」です。30字以内の答案では、出庫対象在庫数量と倉庫内在庫数量の大小関係を明示します。
設問2(3)
図3ではFOR UPDATEを指定したカーソルでFETCHし、読み込んだ行に専有ロックを掛けたまま判定と更新をします。これで、ほかのAPが途中で同じ行を読み書きできなくなります。カーソルが現在位置している行を更新する構文はWHERE CURRENT OF カーソル名なので、公式解答例はCURRENTです。
設問3(1)(ア)
出庫番号の範囲で処理を割り振ると、同じ倉庫・同じ部品に対する出庫が複数のプロセスに分かれて入ります。“在庫”行は倉庫コードと部品番号で特定されるので、公式解答例ではアを倉庫コードとしています(イとは順不同)。
設問3(1)(イ)
アと組み合わせて“在庫”の行を特定するもう一方の主キー列が部品番号です。公式解答例はイを部品番号とし、アとは順不同としています。
設問3(1)(ウ)
図4の2-1と2-2では“在庫”テーブルを更新します。複数のプロセスが同じ“在庫”行を更新しようとして競合するので、公式解答例は在庫です。
設問3(1)(エ)
REPEATABLE READでは更新時の専有ロックをトランザクションの終了まで保持します。図4の3により、COMMITは指定範囲のすべての行を処理し終えてから実行されます。そのため、ある“在庫”行を更新したプロセスが範囲全体を処理し終えるまで、ほかのプロセスはその行の更新を待たされます。公式解答例は「ロックの解放待ち」です。採点講評では、エの正答率が低かったとされています。
設問3(2)(オ)
“在庫”行の競合をなくすには、同じ在庫行に対応する出庫が必ず同じプロセスに入るように割り振ればよいです。“出庫”テーブルで“在庫”の倉庫コードにあたる列は出庫元倉庫コードなので、公式解答例ではオを出庫元倉庫コードとしています(カとは順不同)。処理順もこの列の昇順にそろえます。
設問3(2)(カ)
“在庫”のもう一方の主キー列に対応する“出庫”の列が部品番号です。公式解答例はカを部品番号とし、オとは順不同です。出庫元倉庫コードと部品番号の組合せで範囲を指定すれば、各プロセスが更新する“在庫”行は重なりません。
設問3(2)(キ)
範囲指定と並べ替えの対象は“出庫”テーブルの出庫元倉庫コード列と部品番号列です。複数列索引はこのテーブルに定義するので、公式解答例は出庫です。
設問3(2)(ク)
〔RDBMSの排他制御〕(2)に、索引を使わずにテーブルスキャンすると、条件に合うかどうかに関係なく全行がロック対象になるとあります。索引がなければ、自プロセスの対象行かどうかを判定するための参照がテーブルスキャンになります。そのため、公式解答例はテーブルスキャンです。採点講評では、クの正答率が低かったとされています。
設問3(2)(ケ)
テーブルスキャンでは他プロセスの担当行も参照します。他プロセスが図4の2-3で処理状況を更新した“出庫”行には、COMMITまで専有ロックが掛かっています。その行を参照しようとすると、専有ロックの解放を待つことになります。公式解答例は「更新」または「専有ロック」です。採点講評にあるとおり、問題文で与えられた排他制御の仕組みを落ち着いて当てはめれば導けます。
学習のポイント
共有ロックと専有ロックの両立性、ISOLATIONレベルによるロック保持期間の違い、同じ行で起きるデッドロックの仕組み、WHERE CURRENT OFの使い方、並列処理ではロック対象が重ならないように処理を割り振ること、索引がない場合のテーブルスキャンで全行がロックされることを押さえます。
出典:独立行政法人 情報処理推進機構(IPA)平成29年度春期 データベーススペシャリスト試験 午後Ⅰ 問2(公式資料:問題冊子(PDF) / 解答例 / 採点講評)
関連する過去問一覧
IPA Advancedは非公式の学習サイトです。解説にはAIによる補助生成を含む場合があります。公式の問題冊子・解答例・採点講評を優先し、誤りは確認後に訂正します。運営・編集方針