3-1トランザクション管理
12月の第1週、こむぎ堂はクリスマスケーキの予約を受け付け始めました。店頭のレジでも、ネットの予約画面でも申し込めます。受付の3日目、苺のケーキは残り1台になっていました。夕方5時すぎ、レジでミナトが常連のお客さんの予約を入れたのとほぼ同じ瞬間に、ネットからも同じケーキの予約が届きます。画面にはどちらにも「受け付けました」と出て、ケーキの箱には予約票が2枚貼られることになりました。その夜、予約が立て込んでいた9時すぎには、店のサーバの電源が落ちます。翌朝、最後の数件の予約が入ったのか消えたのか、誰にも分かりませんでした。店長は予約票の束を前に言います。「表に作り直したから、もう取り違えは起きないと思っていたんだけどね」
ミナトが相棒に二つの出来事を説明すると、返ってきたのは問いでした。「ケーキの予約を1件入れるとき、データベースの中では何が書き換わっている?」。考えてみると、書き換わるのは一か所ではありません。予約の表に1行を足し、ケーキの在庫の数を1つ減らします。予約の行だけが入って在庫が減らなければ、ケーキが余っているように見えてしまいます。在庫だけが減って予約の行が無ければ、誰のためのケーキか分からなくなります。
このように、ひとまとまりで行わなければ意味をなさない一連の処理の単位をトランザクションといいます。「予約の行を足す」と「在庫を1減らす」は、二つ合わせて一つのトランザクションです。トランザクションは途中で分けられず、最後まで全部が反映されるか、何もしなかったことにするかのどちらかになります。全部を反映して確定させることをコミット、途中までの更新を取り消して何もしなかった状態に戻すことをロールバックといいます。停電の夜に起きたのは、まさにこの「途中」が残っているかどうか分からない状態でした。
トランザクションが守るべき性質は、英語の頭文字をとってACID特性と呼ばれる四つにまとめられています。A(Atomicity)は、全部実行されるか全く実行されないかのどちらかになること。C(Consistency、一貫性)は、処理の前後でデータの決まりごとが守られていること(在庫がマイナスにならない、など)。I(Isolation、独立性)は、同時に動く複数のトランザクションが互いに影響せず、一つずつ順に行ったときと同じ結果になること。D(Durability)は、いったん確定した結果は、その後に障害が起きても失われないことです。
二つの出来事を四つの性質に当てはめると、どこが崩れたかが見えてきます。残り1台に予約が2件入ったのは、同時に動いたレジとネットの処理が互いに影響した結果で、Iが守られていません。停電の夜は、確定したはずの予約が残っているか(D)、途中の予約が半分だけ残っていないか(A)が分からなくなった出来事です。
ここから基本情報!確定と取消しの仕組み
ACID特性のうちAとDは、日本語の名前でも問われます。トランザクションを分けられない一つの単位として扱い、中途半端な結果を残さない性質が原子性(Atomicity)です。トランザクションの結果を確定させた後は、システムが止まってもその結果が残り続ける性質が耐久性(Durability)です。
この二つを実際に守るのがコミットメント制御です。トランザクションの単位で、処理がすべて正しく終わったらCOMMIT文で更新を確定し、途中で失敗したらROLLBACK文でそのトランザクションの更新をすべて取り消す、という管理をDBMSが行います。ケーキの予約なら、予約の行を足した後に在庫の更新が失敗した時点でROLLBACKし、足した行も消します。
トランザクションは、終わり方によって次のような状態をたどります。
| 終わり方 | 途中の状態 | 終わった状態 |
|---|---|---|
| 正常に終わる | コミット処理中:更新を確定する処理を実行している途中 | コミット済:更新が確定し、障害が起きても失われない |
| 異常で終わる | アボート処理中:異常終了が決まり、更新を取り消している途中 | アボート済:取消しが終わり、更新前の状態に戻った |
アボートはトランザクションを中止することで、その中で行う取消しがロールバックです。コミット処理中に障害が起きたトランザクションは、まだコミット済ではないので、確定した結果としては扱われません。
コミットのたびに、確定の記録をディスクへ書き込む必要があります。ディスクへの書き込みはメモリの操作よりずっと遅いので、予約が1秒に何十件も入ると、その待ち時間が積み重なります。そこで、近い時刻に届いた複数のコミットの記録をまとめて1回で書き込み、書き込みの回数を減らす方法があります。これをグループコミットメント(グループコミット)といいます。
基本情報の範囲ここまで
3-2同時実行制御
ミナトは、予約が2件入った夕方5時すぎの記録を、時刻の順に並べてみました。レジの処理が在庫を読んだのが5時3分10秒、値は1。ネットの処理が在庫を読んだのも5時3分10秒で、値は1。どちらも「まだ1台ある」と判断して予約の行を足し、在庫を0に書き換えていました。
二つの処理は、どちらも間違ったことはしていません。それぞれ、読んだ時点では正しく「残り1台」を見ていました。問題は、レジの処理が在庫を読んでから書き換えるまでの間に、ネットの処理が同じ在庫を読んでしまったことです。後から書いた側の更新が、先の更新を打ち消してしまい、在庫は1台分しか減っていないのに予約は2件になりました。
複数のトランザクションが同じデータを同時に読み書きしても、データの整合性が崩れないように順番を整える仕組みを同時実行制御(排他制御)といいます。代表的な方法は、データを使っている間、そのデータに「使用中」の札をかけておく方法で、この札をロックと呼びます。レジの処理がケーキの在庫にロックをかけていれば、ネットの処理は在庫を読む前に待たされます。レジの処理が終わってロックを外してから在庫を読むと、値はもう0なので、ネットのお客さんには「売り切れ」と返せます。
ここから基本情報!ロックの種類と大きさ
データに札をかけて順番を守らせるやり方をロック方式といい、札の種類は二つあります。一つは、データを書き換えるときにかけるロックで、かけている間はほかのトランザクションが読むことも書くこともできません。これを専有ロック(排他ロック)と呼び、占有ロックと書くこともあります。シラバスの表記は「専有ロック」です。もう一つは、データを読むだけのときにかけるロックで、ほかのトランザクションも同時に読めますが、書き換えはできません。これを共有ロックといいます。
ケーキの在庫を見るだけのお客さんなら何人いてもかまいませんが、書き換える処理は一度に一つずつにしたい。ロックの種類の使い分けは、この考え方を形にしたものです。あるデータにロックがかかっているとき、別のトランザクションが同じデータに続けてロックをかけられるかどうかの関係をロックの両立性といいます。
| 先にかかっているロック | 後から共有ロック | 後から専有ロック |
|---|---|---|
| 共有ロック | かけられる | 待たされる |
| 専有ロック | 待たされる | 待たされる |
両方がかけられるのは、共有ロック同士の組み合わせだけです。
ロックをかける範囲の大きさをロック粒度といいます。苺のケーキの在庫の行だけにロックをかければ、同じ時刻にチョコのケーキの予約は待たずに進められます。表全体にロックをかけると、ケーキの予約はすべて一列に並ぶことになります。粒度を細かくすると同時に進められる処理が増えますが、管理するロックの数が増えるので、その手間は大きくなります。粒度を粗くすると、管理は楽になる代わりに待ちが増えます。
ロックのほかに、資源の使用中・空きを数の値で管理し、その値を増やしたり減らしたりして順番を守らせるセマフォ方式もあります。値が0の間は、資源を使おうとした処理は空きが出るまで待たされます。
基本情報の範囲ここまで
ロックで順番を守らせると、別の困りごとが出てきます。夜の予約で、トランザクションAが苺のケーキの在庫にロックをかけ、次にろうそくの在庫を使おうとしました。同じころトランザクションBは、ろうそくの在庫にロックをかけた後、苺のケーキの在庫を使おうとしています。AはBがろうそくのロックを外すのを待ち、BはAがケーキのロックを外すのを待ちます。どちらも相手が先に終わるのを待っているので、いつまでたっても進みません。
このように、複数のトランザクションが互いに相手の持つロックの解放を待ち合い、どれも処理を進められなくなる状態をデッドロックといいます。起きてしまったら、片方のトランザクションを取り消してロックを外させ、後からやり直させるしかありません。起こりにくくするには、ロックをかける順番を全員でそろえておきます(必ずケーキが先、ろうそくが後、のように)。
デッドロックに気づく方法の一つがタイマ監視です。待ち時間に上限を決めておき、それを超えても待ちが終わらなければ異常とみなして、取り消しなどの手当てをします。たとえば「10秒待ってもロックが取れなければ、その予約の処理を取り消してやり直す」という決まりにすると、デッドロックに陥った処理も10秒後には動き出します。
ここから基本情報!順番の正しさを保つ
同時に動いたトランザクションの結果が、どれか一つずつ順に実行したときの結果と同じになっていれば、整合性は保たれています。この性質を直列可能性といいます。並行して動くトランザクションの読み書きの順番を調整し、直列可能性を保つことをトランザクションスケジューリングと呼びます。夕方5時すぎの二つの予約は、どちらの順で一つずつ行っても「1件は予約、1件は売り切れ」になるはずなので、「2件とも予約」という結果は直列可能ではありません。
直列可能性を保証する代表的なロックの使い方が2相ロック(2相ロッキングプロトコル)です。トランザクションの中を、ロックをかけていくだけの段階(成長相)と、ロックを外していくだけの段階(縮退相)の二つに分け、一度でもロックを外したら、そのトランザクションでは新しいロックをかけないという決まりです。この決まりを守っても、デッドロックは起こりえます。成長相の途中で、二つのトランザクションが互いのロックを待つことがあるからです。
多くの予約を同時にさばくには、受け付ける側の作りも関わります。1つのプロセスの中に複数のスレッド(処理の流れ)を作り、それぞれに別の予約を並行して処理させる方式をマルチスレッド化(マルチスレッド)といいます。予約ごとにプロセスを新しく作るより、作成や切り替えの負担が小さくて済みます。ただし、同じデータを複数のスレッドが同時に触れば、ここまでと同じ順番の問題が起きるので、排他の仕組みが要ります。
基本情報の範囲ここまで
3-3障害回復
停電の翌朝、ミナトはサーバを起動して、予約の表を開きました。店ではいつも、閉店後の夜8時にデータベース全体を外付けのディスクへ複製しています。けれども、停電が起きたのは9時すぎです。8時の複製に戻すだけでは、その後の1時間に入った予約がまるごと消えてしまいます。
システムに障害が起きたとき、データベースを、整合性のとれた障害直前の状態に戻すことを障害回復といいます。そのための材料は二つあります。一つは、ある時点のデータベースの中身をまるごと写しておいたバックアップです。もう一つは、データベースへの更新を一件ずつ記録したもので、更新の前の値と後の値が残っています。
バックアップから、データベースを複製した時点の内容に戻す操作をリストア(復元)といいます。夜8時の複製をリストアすれば、データベースは8時の状態になります。そこから先は、更新の記録を使って埋めていきます。
更新の記録を、いちばん古いものから全部読み直していては、戻すのに時間がかかります。そこで、一定の間隔でメモリ上にある更新の内容をディスクへ書き出し、「ここまではディスクに反映済み」という区切りを付けます。この区切りをチェックポイントといいます。障害が起きたら、直前のチェックポイントから回復の処理を始めればよいので、読み直す記録が少なくて済みます。
ここから基本情報!回復に使う記録
データベースへの更新の履歴を、更新前の値(更新前情報)と更新後の値(更新後情報)の組で記録したファイルをジャーナルファイル(ログファイル)といいます。トランザクションの単位で処理の内容を記録したものなので、トランザクションログ(ジャーナル)とも呼ばれます。どのトランザクションがいつ始まり、いつコミットされたかも、ここに残ります。
チェックポイントの時点で、メモリ上にある更新の内容をディスクへ書き出すことをチェックポイントダンプと呼ぶことがあります。これに対して、データベースの内容を丸ごと別の媒体へ写す処理がデータベースダンプで、こむぎ堂が毎晩8時に行っている複製がこれにあたります。ディスクそのものが故障したときは、データベースダンプが回復の出発点になります。
障害が起きたとき、ジャーナルファイルとバックアップを使って、どのトランザクションをやり直し、どれを取り消すかを判断して回復を進めるDBMSの働きをリカバリ制御といいます。
基本情報の範囲ここまで
回復の方法は、向きの違う二つがあります。更新の記録にある更新前の値を使って、トランザクションが行った更新を、更新前の状態までさかのぼって取り消す方法がバックワードリカバリ(ロールバック)です。バックアップをリストアした後、更新の記録にある更新後の値を順に当て直して、障害の直前の状態まで処理をやり直す方法がフォワードリカバリ(ロールフォワード)です。
どちらを使うかは、障害の時点でトランザクションがコミットされていたかどうかで決まります。停電の夜を例に、チェックポイントを夜9時、停電を9時20分として、三つの予約の扱いを見てみます。
| 予約 | いつ始まり、いつコミットされたか | 回復のしかた |
|---|---|---|
| 予約1 | 8時50分に始まり、8時55分にコミット | チェックポイントでディスクに書き出し済みなので、何もしない |
| 予約2 | 9時5分に始まり、9時10分にコミット | コミット済みだが、ディスクに書き出されていない可能性がある。ロールフォワードでやり直す |
| 予約3 | 8時58分に始まり、停電の時点でコミット前 | チェックポイントで途中の更新までディスクに書き出されている。ロールバックで取り消す |
予約2はお客さんに「受け付けました」と返したものなので、消すわけにはいきません(耐久性の約束です)。予約3はまだ返事をしていないので、取り消して、お客さんにもう一度申し込んでもらえば済みます。予約の行だけが入って在庫が減っていない、という半端な状態は、どちらの方法を使っても残りません。
ここから基本情報!再開の方式とそのほかの回復
障害の後でシステムを再開する方式にも名前があります。チェックポイントの情報とジャーナルファイルを使い、障害の直前の状態を短い時間で作り直して処理を再開する方式がウォームスタートです。停電の翌朝にミナトが行うのは、この方式です。これに対して、障害の直前の情報を使わず、システムを初めの状態から立ち上げ直す方式がコールドスタートです。ディスクが故障したときのように、データベースをバックアップから作り直してから再開するので、ウォームスタートより時間がかかります。
ジャーナルファイルを使わない回復の方法もあります。更新するときに、元のページ(ディスク上でデータを読み書きする単位)を書き換えず、別の場所に新しいページを作って書き込みます。コミットした時点で新しいページに切り替え、それまでは元のページを残しておきます。この元のページをシャドウページと呼び、障害が起きたら元のページに戻すだけで、更新前の状態に回復できます。
障害とは別に、長く使っていると遅くなる問題もあります。予約の行の追加と削除をくり返すうちに、ディスク上のデータが飛び飛びに置かれ、予定の領域に入りきらなかったデータがあふれ用の領域(オーバフロー領域)にたまっていきます。そうなると、一つのデータを読むのにディスクのあちこちを読むことになります。データの格納場所を整理し直して読み書きの効率を取り戻す処理をデータベースの再編成といいます。
基本情報の範囲ここまで
3-4性能向上とインデックス
予約の受け取り日の朝、お客さんが「電話番号で予約したんですけど」とレジに来ました。ミナトが電話番号で探すと、画面が答えを出すまでに数秒かかります。後ろには5人が並んでいました。
お客さんの表には、電話番号の順に並んでいるわけではない行が、何千行もあります。電話番号で探すと、DBMSは1行目から順に、全部の行の電話番号を見比べるしかありません。本の中から一つの言葉を探すのに、1ページ目から読み通すのと同じです。
本なら、巻末の索引を引けば、その言葉が何ページにあるかがすぐ分かります。データベースにも同じ仕組みがあり、探すのに使う列の値と、その値を持つ行の置き場所を対応させて、別に記録しておきます。これをインデックス(索引)といいます。電話番号の列にインデックスを作れば、DBMSは全部の行を見ずに、目当ての行へたどり着けます。
ここから基本情報!インデックスの種類と使い方
インデックスは、作れば作るほどよいわけではありません。表に作ったインデックスの個数をインデックス数といい、多いほど検索に使える道は増えますが、行を追加・変更・削除するたびに、すべてのインデックスも書き直すことになります。予約が殺到する12月に、使わないインデックスまで書き直していれば、それだけデータベースの負荷(処理にかかる仕事の量)が増えます。探し方の多い列にしぼって作るのが基本です。
インデックスの作りにはいくつか種類があり、得意な探し方が違います。
| 種類 | 仕組み | 向いている使い方 |
|---|---|---|
| B-treeインデックス(Bツリーインデックス) | 値の大小で枝分かれする、どの枝も同じ深さにそろった木の形 | 一つの値を探すことも、範囲で探すこともできる。多くのRDBMSで標準 |
| B+木インデックス | B木を改良し、データの置き場所はすべて一番下の葉に持たせ、葉同士を横につなぐ | 葉を横にたどれるので、範囲での検索が速い |
| ビットマップインデックス | 列の値ごとに、各行がその値を持つかを0と1の並びで表す | 受け取り方法や曜日のように、値の種類が少ない列 |
| ハッシュインデックス | ハッシュ関数で値を置き場所の番号に変える | 「=」で一つの値を探すのは速いが、範囲での検索には向かない |
B-treeインデックスがなぜ速いかは、数で見ると分かります。木の一つの節から100本の枝に分かれるとすると、1段目で100通り、2段目で100×100=10,000通りに行き先を分けられます。お客さんが1万人いても、2段たどれば目当ての行の場所が分かります。インデックスが無ければ、最悪で1万行を見比べることになります。
ビットマップインデックスは、小さな例で見ると形が分かります。予約1〜5の受け取り方法が「店頭、配送、店頭、店頭、配送」なら、「店頭」のビット列は10110、「配送」のビット列は01001です。「店頭で受け取る、土曜の予約」を探すときは、店頭のビット列と土曜のビット列の論理積をとるだけで、両方に当てはまる行が分かります。
インデックスには、検索を速くする以外の役割を持たせることもできます。インデックスを作る列の値が、表の中で重複しないことを保証するものをユニークインデックスといいます。電話番号の列にユニークインデックスを作れば、同じ電話番号のお客さんを2回登録しようとしたときに、DBMSが受け付けません。また、インデックスのキーの順に、表のデータそのものをディスク上で並べて格納するものをクラスタ化インデックスといいます。データの並びは一通りしかとれないので、1つの表に作れるのは1つだけです。受け取り日でクラスタ化しておけば、「12月24日の予約」はディスク上でまとまって置かれ、続けて読み出せます。
問合せに必要な列が、すべてインデックスの中に含まれているものをカバリングインデックスといいます。「電話番号から名前を知りたい」だけなら、電話番号と名前を一緒に持つインデックスを作っておくと、表の本体を読みに行かずにインデックスだけで答えが出ます。
文章の中から言葉を探すときは、別の作りを使います。言葉をキーとして、その言葉を含む文書や行の一覧を記録したものが転置インデックスです。ネットに寄せられた口コミから「しっとり」を含むものを探すとき、口コミを全部読まなくても、「しっとり」の項目を見れば、どの口コミに出てくるかが分かります。全文検索の仕組みに使われています。
インデックスを作っても、実際に使うかどうかを決めるのはDBMSです。SQL文を受け取ると、表の行数や値の散らばり方などの統計情報から、どのインデックスを使い、どの順で表を読むかという実行計画を立て、いちばん速そうな方法を選びます。この働きを持つ部分をオプティマイザといいます。行数の少ない表なら、インデックスを使わずに全部読むほうが速いと判断することもあります。
表の結合のやり方も、速さを左右します。結合する二つの表を、結合に使う列の値で並べ替えておき、両方の先頭から順に値を見比べて結合する方法をソートマージ結合法といいます。予約の表とお客さんの表をお客さん番号の順に並べておけば、どちらも1回ずつ上から読むだけで、結合する行の組をすべて見つけられます。
基本情報の範囲ここまで
3-5データへのアクセス制御
12月の土日は、短期のアルバイトが2人、レジに入ります。店長は少し心配そうです。「予約を確かめてもらうのはいいんだけど、間違えて予約を消されたら困るんだよね」
データベースでは、誰がどのデータに何をしてよいかを、利用者ごとに決められます。データベースに接続できるか、データを見られるか、新しく登録できるか、書き換えられるか、消せるか。これらを別々に許したり禁じたりできるので、短期のアルバイトには「予約の表を見ることだけ」を許しておけば、店長の心配はなくなります。
ここから基本情報!アクセス権限の種類
表のデータをSELECT文で検索して見ることを許す権限が参照権限、INSERT文で新しい行を追加することを許す権限が挿入権限、DELETE文で行を削除することを許す権限が削除権限です。このほかに、UPDATE文で値を書き換えることを許す更新権限もあります。権限は、GRANT文で利用者に与え、REVOKE文で取り上げます。
短期のアルバイトには予約の表の参照権限だけを与え、予約を受け付けるミナトには参照権限と挿入権限と更新権限を、予約の取消しを決められる店長には削除権限まで与える、という分け方ができます。仕事に要る最小限の権限だけを与えておけば、操作を間違えたときの被害も、そのIDが盗まれたときの被害も小さくできます。
基本情報の範囲ここまで
3-6データベースの応用
クリスマスが終わった27日、店長が言いました。「今年は苺のケーキが早く売り切れて、チョコは12台も余った。来年は何を何台焼けばいいんだろう」。ミナトの手元には、1年分の予約の記録が丸ごと残っています。
毎日の予約を受け付けるときのデータベースの使い方と、1年分の記録から傾向を探るときの使い方は、性質がまったく違います。前者は、1件ずつの小さな読み書きを、すぐに、正しく、たくさん処理することが求められます。後者は、大量の記録をまとめて読み、曜日や天気ごとに集計することが中心で、書き換えはほとんどしません。
集める記録の量や種類が増え、従来のデータベースの仕組みでは扱いきれなくなったデータの集まりをビッグデータといいます。量が多いだけでなく、文章・画像・センサの値など形式がさまざまで、次々に生まれ続けることも特徴です。こむぎ堂の1年分の予約は、まだビッグデータと呼ぶほどの量ではありません。それでも、ためた記録から次の判断の材料を取り出すという考え方は、規模が大きくなっても同じです。
ここから基本情報!業務の処理と分析の処理
予約の受付やレジの会計のように、多数の利用者から届く小さなトランザクションを、その場ですぐに処理する方式をOLTP(Online Transaction Processing)といいます。これに対して、ためたデータをいろいろな切り口で集計・分析する処理をOLAP(Online Analytical Processing)といいます。「月別・商品別・天気別の予約数」のように、切り口を入れ替えながら数字を見ていく使い方です。
分析のためのデータは、日々の予約のデータベースとは別の場所に集めます。業務のシステムから必要なデータを集め、時系列で蓄積した分析用のデータベースをデータウェアハウスといいます。そのうち、特定の部門や目的に必要な分だけを切り出した小さなデータベースをデータマートと呼びます。こむぎ堂なら、ケーキの予約だけを集めた「クリスマス用」のデータマートが作れます。ためたデータから、人が気づいていなかった規則性や関係を見つけ出す手法はデータマイニングといいます。
業務のデータを分析用のデータベースへ移すとき、そのまま写すことはできません。レジの記録とネットの記録では、商品名の書き方も日付の形式も違うからです。データを取り出し(Extract)、形をそろえて変換し(Transform)、格納先へ書き込む(Load)という順で行う方法をETLといいます。これに対して、取り出したデータを先に格納先へそのまま書き込み(Load)、格納先の側で変換する(Transform)方法をELTといいます。ELTは、格納先の処理能力が高く、元のデータも残しておきたいときに使われます。
データベースの応用は、分析だけではありません。見積書・契約書・マニュアルなどの文書を登録し、保管・検索し、どれが最新版かという改訂の履歴まで管理するシステムを文書管理システムといいます。お客さんとのやり取りや商談の進み具合を記録して、営業の活動を助ける営業支援システムも、データベースの上に作られています。
基本情報の範囲ここまで
27日の夕方、ミナトは去年と今年の予約を曜日と天気で並べた表を店長に見せました。雨の日の予約はチョコに偏っています。来年の焼く数の見積もりは、この表から始めることになりました。
3-7分散データベース
年が明けて、こむぎ堂は駅前に2号店を出すことになりました。2号店にもサーバを置き、2号店の在庫は2号店で管理します。ところが、ネットの予約は「本店でも2号店でも受け取れる」ようにしたい。2号店で受けた予約が、本店の在庫も減らすことがあります。
2号店で受けた1件の予約が、2号店のデータベースと本店のデータベースの両方を書き換えることがあります。片方だけ書き換わってもう片方が失敗すれば、3-1で見た「予約の行だけが入って在庫が減っていない」状態が、店をまたいで起きてしまいます。複数のサーバやデータベースにまたがる処理を、一つのトランザクションとして扱い、全体の整合性を保つものを分散トランザクションといいます。
ここから基本情報!分かれていても一つに見せる
ネットワークでつながった複数の場所(サイト)にデータを分けて置きながら、使う人からは一つのデータベースとして扱えるようにしたものを分散データベースといいます。データがどこにあるか、どのように分けたり複製したりしているかを、使う人が意識しなくてよい性質を透過性といいます。ネットの予約画面を作るときに、「この在庫は2号店のサーバにある」と書き分けなくてよければ、透過性が保たれています。
基本情報の範囲ここまで
分散トランザクションで、すべての場所の更新をそろえて確定させる代表的な方法が2相コミットメント(2相コミット)です。まとめ役の場所が、更新に関わるすべての場所に「コミットできる状態か」を問い合わせます(第1相)。すべての場所から「できる」と返ってきたときだけ、全員に「コミットせよ」と伝えて確定させます(第2相)。一つでも「できない」と返ってきたり、返事が来なかったりしたら、全員にロールバックを指示します。2号店の予約なら、本店と2号店の両方が「在庫を減らせる」と答えたときにだけ、予約が確定します。
ここから基本情報!確かめずに確定すると
2相コミットメントと比べられるのが1相コミットメント(1相コミット)です。各サイトがコミットできる状態かを確かめる段階を置かず、いきなりコミットを指示します。一つのデータベースの中で完結するトランザクションなら、それで足ります。分散データベースで使うと、本店はコミットできたのに2号店では失敗した、という食い違いが起きても、それを防げません。2相コミットメントは、この方式に「確かめる」段階を足したものです。
2相コミットメントにも弱みはあります。第1相で「できる」と答えた場所は、第2相の指示が来るまで、確定も取消しもできずに待ちます。その間にまとめ役が止まると、指示が届くまでロックをかけたまま待ち続けることになります。
基本情報の範囲ここまで
本店と2号店の商品の値段や、パンの一覧のように、どちらの店でも同じものを見たいデータもあります。こうしたデータは、片方を更新したら、もう片方の複製も自動で同じ内容にそろえておくと、どちらの店からでも手元のサーバで速く読めます。複製を作り、元のデータの更新を複製先へ反映し続けて、同じ内容に保つ仕組みをレプリケーションといいます。片方のサーバが止まっても、もう片方の複製で営業を続けられるので、障害への備えにもなります。
3-8データ資源管理
2号店の準備をしながら、ミナトは店にあるデータを書き出してみました。レジの売上の記録、ネットの予約、通販サイトに届く口コミ、ショーケースの温度センサが1分ごとに送ってくる値、商品の写真。どれも、いつか役に立ちそうです。けれども、予約の表のような形をしているのは一部だけでした。
データは、形のそろい方で分けられます。売上の記録や予約のように、あらかじめ決めた列の形(スキーマ)に従って行として並べられるデータを構造化データといいます。関係データベースの表に、そのまま入れられます。口コミの文章や商品の写真、店内の音声のように、決まった行と列の形を持たないデータを非構造化データといいます。表に入れて集計するには、そのままでは使えません。
ここから基本情報!形のそろわないデータをためる
二つの間にあるのが半構造化データです。タグやキーで項目を見分けられる構造は持っていますが、行と列が決まった表の形にはなっていません。XMLやJSONが代表例です。通販サイトの注文が {"品名": "食パン", "数": 2} のようなJSONで届くなら、項目名で中身を取り出せますが、注文ごとに項目の数が違ってもかまいません。
温度センサの値のように、途切れずに発生し続け、ためてから処理するのではなく流れてくるそばから処理するデータをストリーミングデータといいます。ショーケースの温度が上がり始めたら、1日分をためてから集計するのでは間に合いません。届いた値をその場で見て、すぐに知らせる必要があります。
形も用途もばらばらなデータを、使い道が決まる前から捨てずにためておく場所がデータレイクです。データを加工せず元の形のまま大量に蓄積し、使うときになってから必要な形を当てはめます。先に形を決めて整えたデータを入れるデータウェアハウスとは、この順番が逆です。データレイクのように大きな量をためる置き場所には、複数のコンピュータのディスクにファイルを分けて置きながら、ネットワーク越しに一つのファイルの体系として扱えるようにする分散ファイルシステムがよく使われます。
データが増えると、データそのものより「どこに、どんな意味のデータがあるか」が分からなくなります。データの名前・意味・形式・格納場所などを記録したもの(メタデータ)をまとめて管理する仕組みの国際規格に、IRDS(Information Resource Dictionary System:情報資源辞書システム)があり、その枠組みはISO/IEC 10027として定められています。ソフトウェアの開発と保守で生まれる設計書やプログラム、データの定義などの情報を一か所にまとめて管理する場所はリポジトリと呼ばれます。
こうした仕組みを使って、データを人やお金と同じ経営の資源と位置づけ、組織全体でデータの定義や名前をそろえ、管理の方針を決める活動をデータアドミニストレーション(DA)といいます。データベースの設計や運用といった技術面を担うデータベース管理者(DBA)に対して、DAはどのデータを持ち、どう名前を付け、誰が責任を持つかという管理の面を担います。本店と2号店で「苺のケーキ」の商品コードが違っていたら、それをそろえるのはDAの仕事です。
基本情報の範囲ここまで
次の年の12月、こむぎ堂は本店と2号店の両方でクリスマスケーキの予約を受け付けました。残り1台になった苺のケーキに、レジとネットから同時に予約が入っても、後の予約には「売り切れ」と返ります。予約が集中した夜に一度だけサーバが止まりましたが、翌朝には、コミット済みの予約はすべて戻り、途中だった1件は取り消されていました。店長は、去年の記録から見積もった数だけケーキを焼き、24日の夕方にはすべて売り切りました。
1年前の夕方5時すぎ、予約票が2枚貼られたケーキの箱を前にして、店長は「表に作り直したから、もう取り違えは起きないと思っていた」と言いました。表の形を整えることで防げたのは、同じお客さんが2回書かれるような、データの置き方の矛盾でした。同時に書き込まれたときの矛盾と、途中で止まったときの矛盾は、表の形では防げません。ロックが順番を守らせ、コミットとロールバックが「全部か、何もなしか」を守らせ、更新の記録とチェックポイントが確定した予約を障害から守りました。そうして守られた1年分の記録が、翌年に焼くケーキの数を決める材料になりました。