ここでは poko2
のメインターゲットとなる MySQL
と PostgreSQL
データベースの操作について極々簡単にまとめておきます。
テストツールやサンプルを動かすとき、データベースを扱います。その時用の簡易
リファレンスとして使って下さい。
データベースのホストOSは Linux
を想定しています。Windows
の場合、
MySQL
はコマンドプロンプトから Linux
と同様の操作になりますし、
PostgreSQL
はCygwin
を利用しますのでやはり Linux
と同様の操作
になるので省略します。
対象となるDBのバージョンは・・・
MySQL : 3.23.58
PostgreSQL : 7.2.2
MySQL:3.x
or PostgreSQL:7.2.x
)が
同じであればその他のバージョンでも同様だと思われます。
なお、以下の説明で誤りがあれば遠慮なく著者に御指摘下さい。著者は MySQL
や PostgreSQL
の卓越した使い手、というわけではありません。
MySQL
, PostgreSQL
ともに本家の方から日本語ドキュメントが公開されて
います。詳細はそちらを参照して下さい。
MySQL:
MySQL Reference ManualPostgreSQL:
PostgreSQL7.1日本語マニュアルレンタルサーバーなどの場合は、データベースサービスを申し込んだ時にデータ
ベース用のユーザー名とパスワードが与えられていると思います。その場合は
この章は読み飛ばしてしまって構いません。
自前でサーバーを用意して実験してる人や、サーバーの管理者を兼任している場合
は、データベースを利用するには(おそらく)そのユーザーを登録する必要がありま
す。
(もしも「自分一人の実験機だから、rootやpostgresユーザーでも全然平気」と
いう場合は読み飛ばしても大丈夫です。)
以下、MySQL
と PostgreSQL
の二つのデータベースにおけるユーザー
登録に必要な作業を簡単にまとめます。
MySQL
でのユーザーとは、一般に "ユーザー名" と "
接続元ホスト名" を "@" 記号で連結した文字列です。
(ホスト名の特殊な記述として、全ホスト名を表す " % "
も使用できます。)
以下に幾つかの例を示します。
root@localhost
: localhost
から "root"という
ユーザー名で接続して来たユーザーroot@'%'
: 特に接続元ホストを指定せず、とにかく "
root" というユーザー名で接続して来たユーザー'%' があれば、localhost
バージョンは不要ではないか、という質問
も出て来ると思います。それに関しては、ユーザー認証テーブルにおいてホスト
名が具体的なユーザーがより上位レコードとしてソートされるので優先されます。
それによるユーザー認証時間の短縮を狙っている・・・のでしょう、多分。
んで、実際の認証ではどうなっているのか・・・を説明します。簡単に。
恐ろしく直観的なイメージで説明してしまうと、MySQL
では DB
に対する
ユーザー認証を次のようなマトリクステーブル(升目表)で処理します。
ユーザー名 / DB名 | mysql | test | user1 | user2 | ...
------------------+-------+------+-------+-------+-----
root@localhost | O | O | O | O | ...
root@'%' | O | O | O | O | ...
user1@localhost | X | X | O | X | ...
user2@localhost | X | X | X | O | ...
これを実装しているのが、mysql
データベースの user
テーブル
と db
テーブルです。(だから上記升目表では、管理者ユーザーを表す
root
ユーザーのみ mysql
への接続が許可されているわけです。)話を本筋に戻し、データベースの作成とユーザーの登録について概説します。
最初にデータベースを作成します。これは管理者権限のユーザー(デフォルトは
root
ユーザー)で作成します。
$ mysql --user=root --password mysql
mysql> CREATE DATABASE user1db
user1db
が作成したデータベース名になります。大文字小文字は区別されますが、
Windowsからの接続やライブラリの関連で、なるべくシステム全体でどちらかに統一
すべきです。mysql
コマンドラインツールで以下の
ように指定するか、接続した後、USE
というSQLコマンドを使います。
$ mysql --user=root --password user1db
or
mysql> USE user1db
データベースの作成の詳細は、以下のリンクを参照して下さい。続いてユーザーを登録します。
MySQL
におけるユーザー登録とは、ユーザーにデータベースを操作する「権限」
を与えるというイメージです。「権限」を与えたり(GRANT
コマンド)、剥奪
(REVOKE
コマンド)したりすることによりユーザーの登録・削除・アクセス権限
の変更を実装しています。
GRANT
, REVOKE
コマンドの正確な書式やオプションは後述のリンクを参照
して下さい。ここでは、PHP
を使って MySQL
にアクセスする一般ユーザー
を登録するための一般的なコマンドを示すにとどめます。
$ mysql --user=root --password mysql
mysql> GRANT ALL PRIVILEGES ON db_name.* TO user_name IDENTIFIED BY 'password'
これで、db_name
データベースに対して一般的な操作権限を有する user_name
ユーザーを登録できました。(もし既に同ユーザーが登録済であれば、上記権限と
パスワードで登録情報が上書きされます)user_name
の書式は、先に述べたユーザー名と接続元を @ でつなげた文字列
になります。パスワードを後から変更したいときは次のコマンドを実行します。
$ mysql --user=root --password mysql
mysql> SET PASSWORD FOR user_name = PASSWORD('password');
一般に、普通の制限ユーザーは
PostgreSQL
でユーザーを作るための簡易コマンド
createuser
のオプションは以下のようになります。
$ createuser -D -A ユーザー名
(もちろんこのコマンドはpostgres
ユーザーでしか実行できません)
ところが・・・これやってしまうと、そのユーザー専用のDBを作れなくなります。
いくらpostgres
ユーザーにsu
しようが、
$ createdb -U ユーザー名 データベース名
してもユーザー名にはDBの作成権限が無いため、データベースを作成できない
わけです。これじゃ卵が先か鶏が先かという話になり兼ねません。
PostgreSQL
において、ユーザーがcreatedb
できるか否かは
pg_shadow
テーブルの usecreatedb
フィールドに依ります。
このフィールドはboolean
型で、't'
ならcreatedb
可能
です。'f'
ならばcreatedb
はできません。
というわけで、つまりです。最初は createdb
可能なユーザーとして
登録し、データベースを作った後、pg_shadow
の usecreatedb
フィールド
を'f'
に手動で変更、createdb
不可能にする という手法が
有効です。
$ su - postgres
(postgres)$ createuser -d -A newuser
(postgres)$ createdb -U newuser -E EUC-JP newdb
(postgres)$ psql -l template1 ( or template0)
template1=# update pg_shadow set usecreatedb = 'f' where usename = 'newuser';
UPDATE 1
template1=# \q
(postgres)$ exit
$
もう一つ方法が有ります。PostgreSQL
では各DBへのアクセスをそのDBのオーナー
という概念を用いて管理しています。テーブルを作ったり消したりは、そのDBの
オーナーでないと実行できないというわけです。
んで、各DBのオーナーは前述の pg_shadow
テーブルの usesysid
で指定できます。各DBは pg_database
というシステムカタログテーブル
で管理されており、その中の datdba
フィールドにオーナーユーザーの
usesysid
が設定されます。
もう一つの方法とは、最初から$ createuser -D -A
でDB作成不可能として
ユーザー登録してしまい、その後適当なDBをpostgresユーザーで作成、その
datdba
フィールドを作成したユーザーの usesysid
にしてしまう。
・・・というわけです。
$ su - postgres
(postgres)$ createuser -D -A newuser
(postgres)$ createdb -E EUC-JP newdb
(postgres)$ psql -l template1
template1=# update pg_database set datdba = (
template1(# select usesysid from pg_shadow where usename = 'newuser'
template1(# )
template1-# where datname = 'newdb';
UPDATE 1
template1=# \q
(postgres)$ exit
$
pg_shadow
や pg_database
等の「システムカタログ」については、
PostgreSQL
のサポートと保守を行っている株式会社SRA
の日本法人が
提供している以下の日本語HTMLマニュアルを参照して下さい。
Chapter 3. システムカタログ
上記マニュアル群に、通常必要とされる操作の全てが解説されています。
ユーザーの権限を変更するにはもっと簡単な SQL コマンドも用意されています。
ALTER USER username
[ WITH PASSWORD 'password' ]
[ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]
[ VALID UNTIL 'abstime' ]
これはPostgreSQL
独自の実装です。詳細はSRAの日本語HTMLマニュアルを探索
して下さい。
mysql
コマンドの主な使い方を紹介します。まずは $ mysql --help
から
の抜粋を示します。
Usage: mysql [OPTIONS] [database]
-h, --host=... Connect to host.
-p[password], --password[=...]
Password to use when connecting to server
If password is not given it's asked from the tty.
-P, --port=... Port number to use for connection.
-S --socket=... Socket file to use for connection.
-u, --user=# User for login if not current user.
ローカルマシンで実行しているMySQL
サーバーに、root
ユーザーで接続
するには:
$ mysql --user=root --password
(この後、パスワード入力プロンプトが表示されます。)
外部マシン、192.168.2.20 にて実行しているMySQL
(ポート5432で実行中)に
user1
ユーザーで接続する(パスワード無し)には:
$ mysql -h 192.168.2.20 -P 5432 --user=user1
mysql
で接続した後は、様々なコマンドでデータベースを探索できます。
show databases;
データベースの一覧を出力します。
use dbname;
dbname
データベースに接続します。
show tables;
現在接続中のデータベースに登録されているテーブルの 一覧を表示します。
describe tablename;
tablename
というテーブル名の
フィールド構造を示します。
show columns from tablename;
同上。
select database();
現在接続中のデータベース名を取得します。
mysql
コマンドラインツールの使い方については
等から調査を開始してみて下さい。
psql
コマンドの主な使い方を紹介します。
$ psql -l
利用可能なデータベースの一覧を出力して終了します。
$ psql -U user1 db1
user1
というユーザー名で db1
というデータベースに接続します。
パスワード認証が無いことを前提としています。
$ psql -U user1 -W db1
パスワード認証を使います。パスワード入力用プロンプトが表示されます。
$ psql -h HOSTNAME -p PORT -U user1 -W db1
外部PostgreSQL
サーバーである HOSTNAME
(ホスト名かIPアドレス)のポート
番号 PORT
に対して、user1
というユーザー名で db1
データベース
に接続を試みます。パスワード認証を使います。
psql
コマンドの詳細に関しては、manをひくか
「II. PostgreSQL クライアントアプリケーション」の「psql」
を参照されると良いでしょう。
テストツールやサンプルの実行に先立ち、SQLクエリが記述されたファイル
をデータベースに読み込ませ、テーブルの作成やデータの登録を実行させておく事が
良く有ります。そのとき必要なのが、SQLコマンドをファイルから読み込み実行する
機能です。
大概はコマンドラインツールのオプション機能になっています。
リダイレクション (<) を使います。
$ mysql --user=user1 --password testsuite < simple_dbmanager.sql
Enter password: (パスワード入力)
user1
で testsuite
データベースに接続し、simple_dbmanager.sql
に記述されているSQLコマンドを先頭から順番に実行します。
psql
コマンドの -f
オプションに続けて、SQLコマンドを記述した
ファイル名を指定します。
$ psql -U user1 -f simple_dbmanager.sql testsuite
上のコマンドでは、テストツールの中の simple_dbmanager.php
が使用する
テーブルやデータを作成するSQLコマンドを記述したファイル、
simple_dbmanager.sql
を testsuite
データベースに対して実行して
います。また、ユーザー名は user1
で接続します。
MySQL
UNIX系のMySQL
では、設定によってはTCP/IP
接続では無く、UNIX独自
のファイルベースの通信手段である「ソケット」を介して接続を待機している場合
があります。
「ソケット」はファイルシステム上の特殊なファイルです。MySQL
では設定
ファイル my.cnf
の socket
項目で指示しています。
(/etc/my.cnf)
[client]
port = 3306
socket = /var/lib/mysql/mysql.sock
[mysqld]
datadir = /var/lib/mysql
port = 3306
socket = /var/lib/mysql/mysql.sock
上記設定だと(おそらく)TCP/IP
3306 番で待機するとともに、
/var/lib/mysql/mysql.sock
ファイルからも待機しています。
この場合、mysql
コマンドからは次の二つのオプションが使用できます。
$ mysql -P(--port=) 3306
$ mysql -S(--socket=) /var/lib/mysql/mysql.sock
設定や、おそらくコンパイル時のオプションによってか TCP/IP
経由の
接続が使えない場合があります。そのようなときはsocket
変数を確認し、
ソケットファイルを介して接続してみて下さい。
ソケットファイル経由でしか通信できないときでも、mysql
コマンドなら
接続できます。
ところがです。 問題はPHP
から接続する場合です。PHP
用のMySQL
インターフェイスである mysql_connect
のホスト部分は、
"host:port"
形式。この状態で "localhost:3306"
してもつながらないわけです。
この場合、port
部分をソケットファイル名にすることができます。
mysql_connect("localhost:/var/lib/mysql/mysql.sock" ...);
とすれば良いわけです。poko2
インターフェイスなら、$SqlConfig
連想
配列で、
$SqlConfig = array(
"DriverClass" => "mysql",
"Host" => "localhost",
"Database" => "testsuite",
"Port" => "/var/lib/mysql/mysql.sock",
...
とすれば大丈夫です・・・と言いたいところですが、まだ完全では有りません。
これでも接続できない場合があります。
この場合、ポート番号に指示したソケットファイルの位置は単純に無視されている
可能性が有ります。ソケットファイルの場所は PHP
側でも設定で持っている
設定を使っているはずです。
(php.ini)
mysql.default_socket /tmp/mysql.sock
といった感じで。こうなるともはや、.htaccess
ファイル(Apacheの設定に
よっては違う名前の場合も有る)を設置し、ディレクトリ単位で設定を上書きする
他ありません。(AllowOverride Options
が有効である必要があります)
(.htaccess)
<IfModule mod_php4.c>
php_value mysql.default_socket /var/lib/mysql/mysql.sock
</IfModule>
PostgreSQL
PostgreSQL
で忘れやすいのが TCP/IP
接続の有効化です。以下の
日本語マニュアルを参照すると問題が解決するかも知れません。