データベースと永続性

情報システム概論 I 

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2005/2006-02-20
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/

■復習

プログラミング言語で記述しているのは、主記憶(メインメモリ)の内容を書 き換えること。内容を書き換えられるのは、主記憶だけ。他のものは、データ をコピーするか保存するだけ。

■目標

ファイルとデータベースの役割を理解する。永続性という考え方を理解する。

■記憶のためのハードウェア

コンピュータの中では、いろいろな種類の記憶のための ハードウェア、すなわち、メモ リが使われている。もっとも重要なものは、メインメモリ(主記憶)と呼ばれ ているもので、単にメモリといった時には、メインメモリを差す。

メインメモリは、IC(Integrated Circuit、シリコンという元素による半導 体で作られた電気回路)でできている。その他に、ハードディスクやフロッピ・ ディスクも重要な記憶のための部品である。

メモリ(RAM(Random Access Memory))
実行中のプログラムを保持する。加工するデータを一時的に保持する。 非常に速い。容量は、ハードディスクよりは小さい。値段が高い。 (揮発的(電源を切ると消えてしまう)。)
ハード・ディスク (HD(Hard Disk), HDD(Hard Disk Drive))
プログラムやデータをデータを保持する。 容量は、メモリより大きい。値段が安い。 (永続的である(電源を切っても残っている)。)

メモリには、数字で番地(アドレス)が付いている。番地を指定して、データ を保存する。番地を指定すると、データが取り出せる。

◆アクセス時間で見た記憶階層

ハードウェア 時間
プロセッサレジスタ 1クロック
L1キャッシュ 数クロック
L2キャッシュ 10クロック
メインメモリ 数十クロック
ハードディスク 数百万クロック

◆仮想記憶(仮想メモリ)

仮想記憶(仮想メモリ、virtual memory)とは、オペレーティングシステムの働きにより、実際に備えているメ モリ容量よりも大きなプログラムを動かすための仕組みである。

主記憶よりも多くのメモリを使うプロセスを仮想記憶で動かす

図 仮想記憶によるプログラム(プロセス)の実行

仮想記憶を使うと、メモリが100Mバイトしかないコンピュータで、200 Mバイトのメモリを使うプログラムを実行することができるようになる。

もともとは、1つのプログラムで実際のメモリ容量以上のものを使うための仕 組みである。最近では、複数のプログラムが使うメモリの総量で考えることも ある。

仮想記憶の基本的なアイディアは、すぐに使うところだけを速いメモリ(IC) に、当分使わない所を、遅いハードディスクに置き、ディスクとメモリの内容 を入れ替えながら仕事を進めることである。この時、速いメモリを主記憶 (main memory, primary storage)、遅いハードディスクを二次記憶(secondary storage)とう。

◆記憶の持続性からみた時の記憶ハードウェア分類

揮発的 (volatile)
電源を切ると消えてしまう。
永続的 (persistent)、不揮発的 (non volatile)
電源を切っても残っている。
仮想記憶は、揮発的なメモリの「容量」を事実上拡大したもの。

永続的なメモリを仮想化して使いやすくしたものが、 ファイルやデータベース。

■ファイル

ハードディスク、CD-ROM、USB フラッシュメモリ等の 永続的な記憶媒体を オペレーティング・システムの働きにより 仮想化して使いやすくしたもの。 ファイルには、名前がある。名前を保存いるための特殊なファイルを、「ディ レクトリ(directory)」という。「フォルダ(folder)」ということもある。

もしも、ファイルに名前がつけられなかったら・・・・。

◆ディレクトリの木構造

ファイルに名前を付ける方法としては、木構造に基づくものが主流。

◆ファイルがどう見えるか

◆ストリーム

もともとは、流れの意味。通信でよくつかう。 プログラムから見た時、ファイルを先頭のバイトから順にアクセスする方法が ある。
FOPEN(3)                 BSD Library Functions Manual                 FOPEN(3)

NAME
     fopen, fdopen, freopen -- stream open functions

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdio.h>

     FILE *
     fopen(const char * restrict path, const char * restrict mode);

     FILE *
     fdopen(int fildes, const char *mode);

     FILE *
     freopen(const char *path, const char *mode, FILE *stream);

DESCRIPTION
     The fopen() function opens the file whose name is the string pointed to
     by path and associates a stream with it.
なぜ、先頭から順にアクセスするのか。 ストリームといっても、早送り、巻戻しくらいはできるものもある。fseek(), lseek()。

◆ランダムアクセス

ハードディスクは、セクタの集まり。 1セクタは、512バイト程度の大きさ。 先頭から順ではなくても、セクタの番号を指定すれば、どんな順番でもアクセ スできる。 (アクセスするのに、3つの番号(面の番号、シリンダ番号、シリンダ内のセ クタ番号)を個別に指定する必要があるディスクもあった。)

ハードディスク上に作られたファイルは、(テープ上に作られたファイルと違っ て)、先頭から順にアクセスだけでなく、メインメモリと同様に、任意の順番 に配列のようにアクセスすることができる。

API

■プログラミング言語から見た永続性

基本的には、プログラミング言語は、メインメモリ(揮発的なメモリ)しかあ つかえない。 永続性なメモリを扱いたい時には、ファイル入出力を通じて扱うことになる。

◆変数

プログラミング言語で、メインメモリを抽象化したもの。

◆配列

プログラミング言語で、メインメモリを抽象化したもの。連続した番地におか れた一様なデータ。
もの 指すもの 内容
メインメモリ 番地(数) バイト単位
配列 添字(index)(数) 任意のデータ単位

◆連想配列(associative array)

添字として、(文字列など)数以外のものが使える。 数でも、連続ではなくて、粗(sparse)なものが使える。

例:Rubyの連想配列。

aa = {};
aa["apple"] = 100;
aa["orange"] = 120;
printf("%d\n", aa["apple"] );
連想配列のことを、プログラミング言語によっては、ハッシュ表ということも ある。
キー (key)
表を検索する時に使うもの。配列の添字相当。
値 (value)
検索の結果得られるもの。
連想配列には含まれていないデータを検索すると、「見つからない」といいう 結果がかえってくる。

◆連想メモリ

ハードウェアでも、(番地を入れたら値が出てくるのではなく)値を入れると 別の値が出てくる少容量のメモリ(連想メモリ)が使われる。

◆ファイルを連想配列として考える

ファイルには名前がある。 ファイル名を入れると、内容が得られる連想配列として考えることができる。

◆人間を連想配列として考える

単なる連想配列だと、人間はコンピュータにはるかに劣る。

◆変数の寿命とスコープ

プログラミング言語の変数には、スコープと寿命がある。
スコープ
空間的な概念。 プログラムの字面上、どの範囲から使えるか。 プログラムで、スコープにない変数をアクセスするとコンパイル時にエラーに なる。
寿命
時間的な概念。 「いつ」、その変数がアクセス可能になり、「いつ」、アクセスできなく なるのか。実行時のタイミング。 無効になった変数を無理やり使うと、何が起るかわからない。(C言語では、 ポインタを通じて、無効になった変数をアクセスできてしまうことがある。)
int x;

f()
{
    int y ;
    static int z ;
}
種類 スコープ 寿命 外部変数 全プログラム プログラムの実行開始から終了まで 普通の局所変数 関数内 その関数の実行中とそこから別関数に飛んでいる間 staticな局所変数 関数内 プログラムの実行開始から終了まで static変数(関数の外に定義) 同一ファイル内 プログラムの実行開始から終了まで
種類 スコープ 寿命
外部変数 全プログラム プログラムの実行開始から終了まで
普通の局所変数 関数内 その関数の実行中とそこから別関数に飛んでいる間
staticな局所変数 関数内 プログラムの実行開始から終了まで
static変数(関数の外に定義) 同一ファイル内 プログラムの実行開始から終了まで

◆永続的な変数

普通のプログラミング言語で記述できるのは、 寿命がいくら長くても、プログラムの実行開始から終了まで。

プログラムの実行開始前にも有効で、終了後にも有効な変数を 考えてみる。これを永続的な変数という。

プログラミング言語で永続的な変数を支援しているものがある。

一般の言語からは、ライブラリ関数で「永続的なハッシュ表(連想配列)」と して扱うことが多い。

◆永続的なハッシュ表を扱うライブラリ

DB は、Database の略だが、情報学類でこれらをデータベースと呼ぶと怒られ る。固有名詞として扱うと安全。

◆永続的なハッシュ表を扱うライブラリ(Ruby DBM)

Ruby では、DBM というライブラリを使うと、 NDBM (Berkeley DB) をハッシュ表のように扱える。 ただし、キーもデータも文字列。(文字列を入れると文字列がかえって来る。)

保存するプログラム [ruby-dbm-store.rb]

#!/usr/local3/bin/ruby

require 'dbm';
db = DBM::open("fruits",0666);
db["apple"] = 100;
db["orange"] = 120;
db.close();

保存されたデータを利用するプログラム [ruby-dbm-print.rb]
#!/usr/local3/bin/ruby

require 'dbm';
db = DBM::open("fruits");
printf("%d\n", db["apple"] );
db.close();

実行例:
% ls fruits.db [←]
ls: fruits.db: No such file or directory
% ./ruby-dbm-store.rb [←]
% ls fruits.db [←]
fruits.db
% file fruits.db [←]
fruits.db: Berkeley DB (Hash, version 7, native byte-order)
% ./ruby-dbm-print.rb  [←]
100
% []

■データベース

複数の応用目的で共有を意図して組織的かつ永続的に格納されたデータ群。

ファイルと同様に、 永続的な記憶媒体を 仮想化して使いやすくしたもの。

ファイルと違い

データベースは、データベース管理システム(DBMS, DataBase Management System)の働きにより作られる。

◆データモデル

DBMSが提供する、対象データとそれに対する操作を規定した共通の枠組み。 例

◆関係データベース

関係データモデルに基づいて作られたデータベース。

「関係」とは、2次元の表。 関係データモデルでは、表の集合としてデータベースを構築する。
サークル
サークル名 部屋番号 電話番号
テニス 101 1011
サッカー 203 4423
社員
社員番号 氏名 基本給与 住所
001 筑波太郎 400 つくば市×××
002 土浦次郎 450 土浦市△△△
003 水戸三郎 450 水戸市○○○
所属
サークル名 社員番号 役職
テニス 001 代表
テニス 002 会計
サッカー 001 一般部員
サッカー 003 幹事

◆関係データベースに対する操作

◆問い合わせ言語

データベースに対して、一般ユーザが操作しやすいように設計された言語。

◆SQL

関係データベースに対する、標準化された問い合わせ言語。 例:データベースの定義
CREATE TABLE サークル
(サークル名 CHAR(20) NOT NULL,
部屋番号 CHAR(3) NOT NULL,
電話番号 CHAR(4) NOT NULL)
例:データベースの検索
SELECT 電話番号
FROM サークル
WHERE 部屋番号='101'

■並行プログラミング

複数のプログラムが共有しているデータを同時に操作しようとしたら何がおき るのか。 スレッドとは、1つのプログラムの中に含まれる並列処理の単位。スレッドの 数だけ、複数の関数が(論理的に)同時に実行される。

◆相互排除

相互排除(mutual exclusion)
ある資源(ファイル、変数、表など)を アクセスできるプロセス(またはスレッド)の数を多くても1つにする。
際どい部分(critical section) (クリティカルセクション) プログラムの字面上、相互排除が必要な部分

◆ロック

もっとも基本的な命令は、lock と unlock
lock();
  相互排除したい部分。
unlock();
あるファイルや関係データベースの表を、1人で、かつ、一度に1つのプログ ラムでしか操作しないなら、ロックは不用。それ以外の時には、必要。

◆デッドロック

複数の資源を相互排除した時に、いくつかの条件が重なるとロックを保持した まま先に進めないプログラムが出てきてしまう。

◆トランザクションの目的

◆トランザクションの意味

商談は、成立するか、しないか。 all or nothing。

歴史:1960年代、テープの時代。 失敗したら、巻き戻す(rollback)。

銀行口座間の預金の移動。

  1. 口座1から出金
  2. 口座2に入金

◆トランザクション・プリミティブ

◆特性(ACID)

Atomic
外の世界からみると1つ。中間状態が見えない。不可分。
Consistency
不変量(invariant)を保つ。例:口座間の預金の移動。預金の総額は不変。
Isolated
並行するトランザクションは、孤立している。直列化可能(serializable)
Durable
Commit すると永続的。

◆直列化可能(serializable)

注意:Javaの serializable とは意味が全く違う。

複数のトランザクションは、並行に実行可能。しかし、その複数のトランザク ションの最終結果は、それらを「ある順序」で「逐次的に」実行した時と同じ結果 になる。

逆に、トランザクションは、直列化可能なスケジュールが存在するなら、並行 に実行してもよい。直列化可能でないなら、トランザクションは、開始を遅ら せるか、アボートする。

◆トランザクションの例

航空券の乗り継ぎの予約のプログラム
Begin_Transaction();
  reserve("NRT-SFO");
  reserve("SFO-JFK");
Commit();
プログラムの記述としては、これだけ。どこにもロックは出てこない。内部的 には、ロックは行われる(ことがある)。

途中の reserve() が失敗したら、トランザクション全体を abort() する。


Last updated: 2006/02/20 04:21:28
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>