クレジットカード会社として国内外で事業を展開しているE 社は,カード利用の増加に伴い,売上登録処理を見直すことにした。 F さんがその見直しを担当した。
〔カード業務システムの概要〕
1.カード利用者による商品の購入から入金までの概要
(1) E社に登録している加盟店で商品を購入したカード利用者(以下,利用者という)は、商品の代金をカードで支払い, カード売上票の控えを受け取る。
(2) 加盟店は, カード売上票を売上票保管センタに送る。 当該センタは,毎月,クレジットカード会社ごとに, カード売上票を基に売上明細ファイルを作成し,各クレジットカード会社に送る。
(3) E社は,毎月末の売上登録処理によって, 売上明細ファイルを基に各カードの利用残高を更新する。 さらに, 利用明細書作成処理によって, カード番号,利用年月日,利用店名,利用金額、支払区分,支払金額, 支払金額合計, 当月獲得ポイント数などを記載したカード利用明細書を作成し、各利用者に送る。
(4) 利用者は,代金を銀行口座振替にすることも, ATM から入金することもできる。 入金した時点で, 即時に入金トランザクションが利用残高を更新する。
2.売上登録処理の概要
(1) 売上登録処理で使用する主なテーブル構造を図1 に, 主な列の説明を表1に, 主なテーブル・列の統計情報及び索引定義情報を表2に示す。 ここで, ページ及び行は追加された順に並び、 同じページに異なるテーブルの行が格納されることはない。 また,ページは,ページ単位で順次又はランダムに磁気ディスク装置からバッファに読み込まれる。
(2) 売上登録処理は、次の三つのジョブから構成される。 現行のジョブ2 で実行するプログラムの処理の流れとSQL文を、 図2に示す。
なお、全てのジョブには,一意なジョブ ID を割り当てる。 また, ISOLATIONレベルは READ COMMITTED であり、 排他制御は行単位で行う。
ジョブ1 売上明細ファイルの各レコードに登録年月を付加し, 加盟店コード,利用年月日順にソートした後, “売上明細” テーブルに追加する。
ジョブ2 “売上明細”テーブルから1行読み込むごとに, カード番号をキーにして“利用残高” テーブルから 1行読み込み、 利用残高に利用金額を加算する(図2の②)。 カード利用明細書の作成に必要な情報を付加した行を,“利用明細” テーブルに追加する (図2の③)。
ジョブ3 当月を含む直近10か月以外の行を, “売上明細” テーブルから削除する。 表2の統計情報は,ジョブ3が終了した直後の値である。
〔売上登録処理の現状調査及び見直し〕
1.Fさんは売上登録処理の現状を調査し, その結果を次のようにまとめた。
(1) 10 か月間に利用されたカードは, (ア)枚であった。 毎月のカード利用件の利用明細が印字されていた。明細書には,カード1枚当たり平均(イ)件の利用明細が印字されていた。
(2) ジョブ2は,毎月平均(ウ)行の売り上げ明細を処理するために、“売上明細” テーブルから副次索引を用いて(エ)ページを順次に読み込み,行がカード番号順に格納されている“利用残高” テーブルから主索引を用いて延べ最大(オ)ページをランダムに読み込んでいた。
(3) ジョブ2は, 重複していない売上明細連番の範囲を指定することで,多重処理できる設計になっている。 しかし, 多重処理すると“(カ)”テーブルの行でデッドロックが発生するので,これまでは1多重で実行していた。
(4) ジョブ2は,最後に1回だけ同期を取っていた。 これは, ジョブ2が異常終了 (以下,失敗という)した場合, 失敗の原因を取り除いた後, ジョブ2 を最初から単純に再実行できるからであった。
(5) 処理量が増えるにつれて, メモリリークなどによってジョブ2が失敗したとき,ジョブ2の終了直前に RDBMS によって行われる (キ)処理の時間が長くなるおそれがある。
(6) 処理量が増えるにつれて, “利用残高” テーブルを更新する入金トランザクションの排他ロック待ち時間が長くなるおそれがある。
2.Fさんの上司であるG部長は,ジョブ2の見直しについて次のように指示した。
指示① 多重処理でもジョブ2でデッドロックが発生しないようにすること
指示② ジョブ2の途中から処理を再開できるように, チェックポイントリスタート機能(以下, C/R 機能という) を追加すること
3.F さんは,G 部長の指示に対し, 売上登録処理を変更した。 その変更内容を表3に示す。
〔チェックポイントリスタート機能の概要〕
F さんは, G 部長の指示②に対し,次のようにジョブ2 が実行するプログラムにC/R 機能を追加した。 C/R 機能を追加した後のプログラムの処理の流れと SQL文を,図3に示す。 図3中の破線で囲んだ部分は, F さんが C/R 機能を追加するために変更した箇所である。
1.“チェックポイント” テーブル (以下, “CKPT” テーブルという) を定義する。
2.ジョブ2 は, “売上明細” テーブルの N行を処理するごとに、 そのときの売上明細連番をチェックポイントとして “CKPT” テーブルに記録し,かつ, COMMIT文を発行することで同期を取る。
3.K を0以上の整数とするとき, 2.の処理の (K+1) 回目の繰返しの途中で処理が失敗した場合,その原因を取り除いて、 同じジョブ ID のジョブを再実行する。そのとき,“売上明細” テーブルのジョブ2で処理すべき行全体の中の (N×K+1)行目から処理を再開する。