E社は,登録している会員向けに健康食品を通信販売する会社である。 情報システム部のFさんは,請求情報照会処理と請求情報更新処理から構成される請求情報処理で使用するテーブルの保守とバックアップ計画の作成を任されている。
〔テーブルのバックアップ, 回復及びロード〕
請求情報処理で使用するテーブルのバックアップ, 回復及びロードは,関係データベース管理システム (RDBMS) が備える機能を使用して行われている。 その概要は,次のとおりである。
1.テーブルのバックアップ
バックアップコマンドによって,テーブルごとにバックアップファイルを作成する。 そのファイルを, イメージコピー(以下, IC という)と呼ぶ。
① IC は,取得するページの範囲によって, 全体IC, 増分IC及び差分IC の3種類に分けられる。
・全体IC には、テーブルの全ページが含まれる。
・増分 IC には,前回の全体 IC 取得後に変更されたすべてのページが含まれる。
・差分IC には,前回の全体 IC 取得後に変更されたページが含まれる。 ただし,前回の全体 IC 取得以降に差分IC を取得していた場合は,前回の差分 IC 取得後に変更されたページだけが含まれる。
② IC は,取得する時期によって, オフライン ICとオンラインICの2種類に分けられる。
・オフライン IC の取得中は,ほかの利用者からのアクセスは参照だけが可能である。
・オンライン IC の取得中は,ほかの利用者からのアクセスはすべての操作 (追加,参照,更新、削除)が可能であり, ICには未コミット状態のデータが含まれることがある。
2.テーブルの回復
IC と RDBMS が回復用に取得するログを入力すれば,回復コマンドによって,テーブルを直近の状態まで回復可能である。 可能な入力の組合せは,次のとおりである。
・全体IC と全体IC 取得後のすべてのログ
・全体ICとすべての差分 IC, 最後の差分 IC 取得後のすべてのログ
・全体IC と最後の増分IC, その増分IC 取得後のすべてのログ
3.テーブルのロード
ロードコマンドによって, 大量のデータを INSERT文よりも効率よくテーブルに追加できる。ログを出力しないオプションを使った場合,ロード後のテーブルへのアクセスは,参照だけが可能であり, 全体 IC を取得すれば, すべての操作が可能になる。
〔テーブルの構造〕
請求情報処理で使用するテーブルの構造を、 図1に示す。
〔請求情報照会処理の概要〕
請求情報照会処理では,図2のSQL 文を使用する。 照会1 と照会2のアクセス経路は主索引(主キーに定義された索引)である。 トランザクションの ISOLATION レベルは REPEATABLE READ であり, 排他は行単位に行われる。
〔請求情報更新処理の概要〕
請求情報更新処理は,請求登録処理,入金登録処理,請求一括削除処理及び請求取消処理から構成される。
1.請求登録処理は,会員を四つのグループに均等に分け, グループ単位に日を分けて,
それぞれ毎月1回, バッチ処理で行う。当処理は, “請求” テーブルと“請求明細”
テーブルに行を追加し, 請求番号ごとに同期点を取る。“請求” テーブルの請求日と“会員” テーブルの最新請求日には処理日を設定し, “商品別請求”テーブルの請求額合計に請求明細行の請求額を加算する。 請求登録処理の後、1か月以内に入金される。
2.入金登録処理は,請求登録処理日に合わせて,バッチ処理で行い,“請求”テーブルの入金日と “会員” テーブルの最新入金日に実際の入金日を設定する。 入金登録処理も,毎回,全会員数の25%を対象にするが,同じ日の請求登録処理対象の会員とは限らないので、二つの処理を合わせて,最大で全会員数の50%が対象になる。
3.請求一括削除処理はバッチ処理で行い, 月末日に入金日を調べて、 請求日が前月の行のうち, 入金済の行を削除する。
4.請求取消処理は,納品後に返品されたとき,“請求” テーブルの請求取消日に返品日を設定し,“請求明細” テーブルの返品フラグを 'N' から ‘Y'に更新する。また,“商品別請求” テーブルの請求額合計から返品対象の請求額を減算する。
テーブルのデータに関する主な特徴は,次のとおりである。
1.年間を通じて扱う全体の商品の種類の数は変わらない。売れる商品は、月平均で全種類の25%である。
2.請求番号には,一意な連番を付与する。 請求明細番号には,請求番号ごとに1からの連番を付与する。
3.“請求明細”テーブルは,一つの請求番号に対して請求明細が平均2行存在する。
4.“請求”テーブル及び “請求明細” テーブルは, 最大 2か月間保存する。両テーブルの行数は,最も多い月で平均的な月の1.2倍となる。 また、 今後、年率 20%以上の増加が見込まれる。
5.“商品別請求” テーブルの請求額合計には、年度決算後に0を設定する。
請求一括削除処理は,図3に示す 2 個の DELETE 文を使って一括削除をする。図3中の削除1と削除2の間で同期点を取るものとする。 ページ中の削除された行の領域は,新たな行の追加のときに再利用可能である。

〔問題の発生・検討〕
Fさんが請求情報更新処理のテストを行ったところ, 次の問題 A〜C が発生した。
問題 A 障害テストを行うために,請求登録処理を意図的に異常終了させた後, そのまま最初から再実行したところ, 請求番号を除き, 同じ内容の請求データ行が追加された。
問題 B 請求一括削除処理では,図3中の削除1 を実行したとき,データ量によって失敗することがあった。
問題 C 請求一括削除処理中は,図2のSQL文を発行するオンライントランザクションが長時間にわたって排他待ちになることがあった。
Fさんは,発生した問題 A〜C について, それぞれ次の検討 A〜C を行った。
検討 A 問題 A の原因は, RDBMS が請求番号に常に一意な番号を自動採番しているからであった。 F さんは, “請求” テーブルに制約を追加することによって解決しようとした。
検討 B 問題 B の原因は,回復用に取得するログの量が1作業単位の許容上限値を超えたからであった。 F さんは, 対策として次の二つの方法を比較し,方法2を選択した。
方法1:1作業単位の許容上限値を20%増加させる。
方法2:一定行数を削除するたびに同期点を取るように, 削除1を変更する。
検討 C 問題 C に対する対策として, 請求情報照会処理のトランザクションのISOLATION REPEATABLE READ 5 READ UNCOMMITTED I変更したところ、長時間の排他待ちは解消したが,照会2では,実行のタイミングによって,請求額合計が少ないという不整合が発生した。 そこで,“請求”テーブルの明細数と “請求明細” テーブルの明細行の数が不一致の場合は,照会結果に含まれないように、 図2中の照会2を図4のように修正した。

〔請求一括削除処理の内容 ・手順の変更〕
Fさんは,検討Cで述べた対策とは別に、問題Cに対する対策として, 請求一括削除処理の手順を表1のように変更した。 このとき, ある手順からある手順の間,オンライントランザクションからの“請求” テーブルと “請求明細” テーブルへのアクセスを停止することにした。 また, 手順 5 の終了後,次の請求一括削除処理を行うまで,差分IC又は増分IC を定期的に取得することにした。
〔テーブルの定期バックアップ計画〕
F さんはまず,請求情報処理の各処理とテーブルの CRUD 及び各処理の稼働情報(処理形態,稼働時間帯及び処理頻度)を調査し, 表2のように整理した。
次に、月末日の請求一括削除処理の終了後に全体 IC を取得し、請求登録処理と入金登録処理の終了後に, 差分 IC 又は増分IC を取得することにした。 バックアップ時間は、その時点のICの容量にほぼ比例することが分かったので,各テーブルの1か月分の全体 IC の容量に対する差分 IC及び増分IC の容量の割合を見積もった。その結果を表3に示す。 ここで,請求取消処理による影響は無視するものとする。