SRA OSS, Inc. 日本支社
今回の運用性評価では、評価用ツールとしてPostgreSQL用のベンチマークツールであるpgbenchを、レプリケーションの確認には今回開発したコンペアツールを使用した。
コマンドを実行するマシンを区別するため、コマンドプロンプトの記述を表1のように定める。 「$」で表されるプロンプトは一般ユーザ、「#」は root ユーザとする。 シェルはbashを使用し、PostgreSQLをインストールした/usr/local/pgsql/binディレクトリにパスが通っているものとする。また、今回開発したコンペアツールはクライアントのホームディレクトリに置き、そこで実行することとする。
| ノード | ホスト名 | コマンドプロンプト |
|---|---|---|
| クライアント | client | [client]$ |
| PostgreSQLマスタサーバ | db1 | [db1]$ |
| PostgreSQLスレーブサーバ | db2 | [db2]$ |
| PostgreSQLスレーブサーバ | db3 | [db3]$ |
Slony-I 1.2.1の導入手順を下記に示す。
Slony-I 1.2.1をソースコードからコンパイルしてインストールする。
Slony-I 1.2.1を展開するディレクトリを作成し、所有者をpostgresユーザに変更する。
[db1/db2]$ su - [db1/db2]# mkdir /usr/local/src/slony1-1.2.1 [db1/db2]# chown postgres:postgres /usr/local/src/slony1-1.2.1
Slony-I 1.2.1のソースコードアーカイブをpgFoundryからダウンロードし、/tmpディレクトリに保存する。そして、postgresユーザになり、/usr/local/srcディレクトリでダウンロードしたアーカイブを展開する。
[db1/db2]# su - postgres [db1/db2]$ cd /usr/local/src [db1/db2]$ tar xjf /tmp/slony1-1.2.1-tar.bz2 [db1/db2]$ cd slony1-1.2.1
Slony-I 1.2.1のソースコードをコンパイルし、インストールする。configureスクリプトの実行時には、--with-pgconfigdirオプションでPostgreSQLの設定ファイルpg_configがあるディレクトリを指定する。
[db1/db2]$ ./configure --with-pgconfigdir=/usr/local/pgsql/bin [db1/db2]$ make all [db1/db2]$ make install
db1サーバに検証用のtest_dbデータベースを作成し、Slony-I 1.2.1が使用する手続き言語plpgsqlをそこに登録する。そして、そのデータベースをpgbenchコマンドで初期化する。
[db1]$ createdb test_db [db1]$ createlang plpgsql test_db [db1]$ pgbench -i test_db
db1サーバのデータベースのスキーマをdb2サーバにコピーする。
[db2]$ createdb test_db [db1]$ pg_dump -s test_db | psql -h db2 test_db
Slony-I 1.2.1の設定は付属のslonikコマンドで行う。設定項目が多いため、db1サーバ上で下記のシェルスクリプトをmaster_setup.shという名前で作成し、実行する。
#!/bin/sh slonik <<_EOF_ cluster name = slony_test; node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; init cluster ( id=1, comment = 'Master'); table add key (node id=1, fully qualified name='public.history'); create set (id=1, origin=1, comment='All tables'); set add table (set id=1, origin=1, id=1, fully qualified name = 'public.accounts', comment='accounts'); set add table (set id=1, origin=1, id=2, fully qualified name = 'public.branches', comment='branches'); set add table (set id=1, origin=1, id=3, fully qualified name = 'public.tellers', comment='tellers'); set add table (set id=1, origin=1, id=4, fully qualified name = 'public.history', comment='history', key=serial); store node (id=2, comment = 'Slave'); store path (server = 1, client = 2, conninfo='test_db host=db1 user=postgres'); store path (server = 2, client = 1, conninfo='test_db host=db2 user=postgres'); store listen (origin=1, provider = 1, receiver =2); store listen (origin=2, provider = 2, receiver =1); _EOF_
[db1]$ ./master_setup.sh
db1サーバとdb2サーバ上でslonデーモンを起動する。
[db1]$ slon slony_test "dbname=test_db user=postgres host=db1" & [db2]$ slon slony_test "dbname=test_db user=postgres host=db2" &
db2サーバ上で下記のスクリプトをslave_setup.shという名前で作成して実行し、レプリケーションを開始する。
#!/bin/sh slonik <<_EOF_ cluster name = slony_test; node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; subscribe set ( id = 1, provider = 1, receiver = 2, forward = no); _EOF_
[db2]$ ./slave_setup.sh
Slony-I 1.2.1の機能評価の手順を下記に示す。
Slony-I 1.2.1のレプリケーション機能をpgbenchと今回開発したコンペアツールpgdiff.shを使用して検証する。
クライアント上で、db1サーバのtest_dbデータベースに対してpgbenchコマンドを実行する。
[client]$ pgbench -h db1 test_db
Slony-I 1.2.1は非同期でレプリケーションを行うため、少し間をおいてからクライアントでpgdiff.shを実行し、データベース間の差異を確認する。db1サーバとdb2サーバのデータベース間でテーブルの内容が一致している場合、各コマンドの実行後には何も表示されない。
[cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
マスタとスレーブの2台の構成に、新たにスレーブを追加する。このとき、新しいスレーブは現在のスレーブに接続する。このような段階的なスレーブの接続をカスケード接続という。
db2サーバのデータベースのスキーマをdb3サーバにコピーする。
[db3]$ createdb test_db [db2]$ pg_dump -s test_db | psql -h db3 test_db
db2サーバ上で下記のコマンドを実行し、db3ノードに関する情報をdb2サーバのslonデーモンに登録する。
[db2]$ slonik <<_EOF_ cluster name = slony_test; node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; node 3 admin conninfo = 'dbname=test_db host=db3 user=postgres'; subscribe set ( id = 1, provider = 1, receiver = 2, forward = yes); store node (id=3, comment = 'Slave2'); store path (server = 2, client = 3, conninfo='dbname=test_db host=db2 user=postgres'); store path (server = 3, client = 2, conninfo='dbname=test_db host=db3 user=postgres'); store listen (origin=3, provider = 3, receiver =2); store listen (origin=2, provider = 2, receiver =3); _EOF_
db3サーバ上でslonデーモンを起動する。
[db3]$ slon slony_test "dbname=test_db user=postgres host=db3" &
db3サーバ上で下記のコマンドを実行し、レプリケーションを開始する。
[db3]$ slonik <<_EOF_ cluster name = slony_test; node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; node 3 admin conninfo = 'dbname=test_db host=db3 user=postgres'; subscribe set ( id = 1, provider = 2, receiver = 3, forward = no); _EOF_
pgbenchとコンペアツールpgdiff.shを使用して、追加したスレーブに正常にレプリケーションされるかどうか検証する。
クライアント上で、db1サーバのtest_dbデータベースに対してpgbenchコマンドを実行する。
[client]$ pgbench -h db1 test_db
少し間をおいてからクライアントでpgdiff.shを実行し、db1サーバとdb2サーバのデータベース間の差異を確認する。db1サーバとdb2サーバのデータベース間でテーブルの内容が一致している場合、各コマンドの実行後には何も表示されない。
[cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
続いて、db2サーバとdb3サーバのデータベース間の差異を確認する。db2サーバとdb3サーバのデータベース間でテーブルの内容が一致している場合、各コマンドの実行後には何も表示されない。以上の操作で、db1サーバ、db2サーバ、db3サーバの各データベース間に差異がないこと、すなわち、追加したスレーブに正常にレプリケーションされるかどうか確認できる。
[cleint]$ ./pgdiff.sh --mhost db2 --shost db3 --database test_db --sortcol aid accounts [cleint]$ ./pgdiff.sh --mhost db2 --shost db3 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db2 --shost db3 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db2 --shost db3 --database test_db --sortcol aid bid tid delta history
スイッチオーバを検証する。スイッチオーバとは、マスタの役割を他のノードに移行する操作のことである。
db1サーバ上で下記のコマンドを実行し、マスタの役割をdb1サーバからdb2サーバに移動する。
[db1]$ slonik <<_EOF_ cluster name = slony_test; node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; lock set (id = 1, origin = 1); wait for event (origin = 1, confirmed = 2); move set (id = 1, old origin = 1, new origin = 2); wait for event (origin = 1, confirmed = 2); _EOF_
pgbenchとコンペアツールpgdiff.shを使用して、マスタの役割が移動したかどうか検証する。
クライアント上で、db2サーバのtest_dbデータベースに対してpgbenchコマンドを実行する。
[client]$ pgbench -h db2 test_db
少し間をおいてからクライアントでpgdiff.shを実行し、db1サーバとdb2サーバのデータベース間の差異を確認する。db1サーバとdb2サーバのデータベース間でテーブルの内容が一致している場合、各コマンドの実行後には何も表示されない。
[cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
クライアント上で、旧マスタ(現スレーブ)のdb1サーバに対してpgbenchコマンドを実行する。スレーブは更新ができないのでエラーが出力されれば、スイッチオーバが実行されたことになる。
[client]$ pgbench -h db1 test_db starting vacuum...ERROR: Slony-I: Table history is replicated and cannot be modified on a subscriber node
フェイルオーバを検証する。フェイルオーバとは障害が起きたマスタを切り離してマスタの役割を他のノードに移行する操作のことである。今回は、障害を起こさずにフェイルオーバを行う。
db2サーバ上で下記のコマンドを実行し、マスタの役割をdb1サーバからdb2サーバに移動する。
[db2]$ slonik <<_EOF_ cluster name = $CLUSTER; node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; failover (id = 1, backup node = 2); _EOF_
pgbenchとコンペアツールpgdiff.shを使用して、マスタの役割が移動したかどうか検証する。
クライアント上で、db2サーバのtest_dbデータベースに対してpgbenchコマンドを実行する。
[client]$ pgbench -h db2 test_db
少し間をおいてからクライアントでpgdiff.shを実行し、db1サーバとdb2サーバのデータベース間の差異を確認する。db1サーバとdb2サーバのデータベース間でテーブルの内容が一致している場合、各コマンドの実行後には何も表示されない。フェイルオーバ後は、db1サーバが切り離されているためレプリケーションは行われていない。そのため、各コマンドの実行後に差異が表示されれば、フェイルオーバが実行されたことになる。
[cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
単体のPostgreSQLで運用しているアプリケーションを、Slony-I 1.2.1を用いたシステムに移行する場合に、注意すべきSQLがあるかどうか検証する。
Slony-I 1.2.1の移行性評価の手順を下記に示す。
検証の前に、検証で使用するテーブルやシーケンスを用意する。
db1サーバのデータベースに各種検証用のテーブルとシーケンスを作成する。Slony-I 1.2.1は、レプリケーションを行うテーブルに主キーを用意した方が設定が容易になるため、テーブルにはすべてPRIMARY KEY制約を付ける。
[db1]$ psql test_db test_db=# CREATE TABLE random_table (number NUMERIC PRIMARY KEY); test_db=# CREATE TABLE timestamp_table (time TIMESTAMP PRIMARY KEY); test_db=# CREATE TABLE serial_table (serial_number SERIAL, query_number TEXT, PRIMARY KEY(serial_number)); test_db=# CREATE TABLE seq_table (seq_number INTEGER, query_number TEXT, PRIMARY KEY(seq_number)); test_db=# CREATE SEQUENCE myseq; test_db=# CREATE TABLE lo_table (o OID, comment TEXT, PRIMARY KEY(o));
db1サーバのデータベースのスキーマをdb2サーバにコピーする。
[db1]$ pg_dump -s test_db | psql -h db2 test_db 2> /dev/null
db1サーバ上で下記のコマンドを実行し、各種検証用のテーブルとシーケンスをレプリケーション対象として登録する。
[db1]$ slonik <<_EOF_ > cluster name = slony_test; > node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; > node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; > create set ( id=2, origin=1, comment='SQL Test' ); > set add table (set id=2, origin=1, id=5, fully qualified name = 'public.random_table', comment='random_table'); > set add table (set id=2, origin=1, id=6, fully qualified name = 'public.timestamp_table', comment='timestamp_table'); > set add table (set id=2, origin=1, id=7, fully qualified name = 'public.serial_table', comment='serial_table'); > set add sequence (set id=2, origin=1, id=7, fully qualified name='public.serial_table_serial_number_seq', comment='sequence serial_table_serial_number_seq'); > set add table (set id=2, origin=1, id=8, fully qualified name = 'public.seq_table', comment='seq_table'); > set add sequence (set id=2, origin=1, id=8, fully qualified name='public.myseq', comment='sequence myseq'); > set add table (set id=2, origin=1, id=9, fully qualified name = 'public.lo_table', comment='lo_table'); > _EOF_
db2サーバ上で下記のコマンドを実行し、各種検証用のテーブルとシーケンスのレプリケーションを開始する。
[db2]$ slonik <<_EOF_ > cluster name = slony_test; > node 1 admin conninfo = 'dbname=test_db host=db1 user=postgres'; > node 2 admin conninfo = 'dbname=test_db host=db2 user=postgres'; > subscribe set ( id = 2, provider = 1, receiver = 2, forward = no); > _EOF_
乱数を使用したSQL文の実行結果が、どのようにレプリケーションされるか検証する。
クライアントからマスタのtest_dbデータベースに接続し、random_tableテーブルに乱数を挿入する。そして、その乱数を確認する。
[client]$ psql -h db1 test_db
test_db=# INSERT INTO random_table VALUES (random());
INSERT 0 1
test_db=# SELECT * FROM random_table;
number
-------------------
0.292244203990439
(1 row)
クライアントからスレーブのtest_dbデータベースに接続し、random_tableテーブルに挿入された乱数を確認する。
[client]$ psql -h db2 test_db
test_db=# SELECT * FROM random_table;
number
-------------------
0.292244203990439
(1 row)
マスタとスレーブで乱数が一致していることを確認する。
CURRENT_TIMESTAMP関数を使用したSQL文の実行結果が、どのようにレプリケーションされるか検証する。
クライアントからマスタのtest_dbデータベースに接続し、timestamp_tableテーブルに現在のタイムスタンプを挿入する。そして、そのタイムスタンプを確認する。
[client]$ psql -h db1 test_db
test_db=# INSERT INTO timestamp_table VALUES (CURRENT_TIMESTAMP);
INSERT 0 1
test_db=# SELECT * FROM timestamp_table;
time
----------------------------
2006-12-04 13:42:41.679315
(1 row)
クライアントからスレーブのtest_dbデータベースに接続し、timestamp_tableテーブルに挿入されたタイムスタンプを確認する。
[client]$ psql -h db2 test_db
test_db=# INSERT INTO timestamp_table VALUES (CURRENT_TIMESTAMP);
INSERT 0 1
test_db=# SELECT * FROM timestamp_table;
time
----------------------------
2006-12-04 13:42:41.679315
(1 row)
マスタとスレーブでタイムスタンプが一致していることを確認する。
マスタとスレーブでOIDが一致しているかどうか確認する。
クライアントからマスタのtest_dbデータベースに接続し、branchesテーブルの1行目のOIDを確認する。
[client]$ psql -h db1 test_db test_db=# SELECT oid, * FROM branches; oid | bid | bbalance | filler -------+-----+----------+-------- 16396 | 1 | 0 | (1 row)
クライアントからスレーブのtest_dbデータベースに接続し、branchesテーブルの1行目のOIDを確認する。
[client]$ psql -h db2 test_db test_db=# SELECT oid, * FROM branches; oid | bid | bbalance | filler --------+-----+----------+-------- 216749 | 1 | 0 | (1 row)
通常、マスタとスレーブでOIDは一致しない。
SERIAL型を使用したSQL文の実行結果が、どのようにレプリケーションされるか検証する。検証は簡単なシェルスクリプトでほぼ同時に100個のデータを挿入し、マスタとスレーブでSERIAL型の値にずれが出ないか確認する。
下記のシェルスクリプトをクライアント上で実行する。
[client]$ for (( i = 1; i <= 100; i++)); do {
> psql -h db1 test_db -c "INSERT INTO serial_table(query_number) VALUES ('Query$i')" &
> }; done;
INSERT 0 1
INSERT 0 1
(以下省略)
クライアント上でpgdiff.shを実行し、マスタとスレーブのserial_tableテーブルの内容が一致していることを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol seq_number serial_table
SEQUENCEを使用したSQL文の実行結果が、どのようにレプリケーションされるか検証する。検証は簡単なシェルスクリプトでほぼ同時に100個のデータを挿入し、マスタとスレーブでSEQUENCEの値にずれが出ないか確認する。
下記のシェルスクリプトをクライアント上で実行する。
[client]$ for (( i = 1; i <= 100; i++)); do {
> psql -h db1 test_db -c "INSERT INTO seq_table VALUES (nextval('myseq'), 'Query$i')" &
> }; done;
INSERT 0 1
INSERT 0 1
(以下省略)
クライアント上でpgdiff.shを実行し、マスタとスレーブのseq_tableテーブルの内容が一致していることを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol seq_number seq_table
マスタとスレーブでトランザクションIDが一致しているかどうか確認する。
クライアントからマスタのtest_dbデータベースに接続し、SEQUENCEの項で作成したseq_tableテーブルの各行のトランザクションIDを確認する。
[client]$ psql -h db1 teest_db test_db=# SELECT xmin, xmax, * FROM seq_table; xmin | xmax | seq_number | query_number -------+------+------------+-------------- 25503 | 0 | 1 | Query1 (以下省略)
クライアントからスレーブのtest_dbデータベースに接続し、SEQUENCEの項で作成したseq_tableテーブルの各行のトランザクションIDを確認する。
[client]$ psql -h db2 teest_db test_db=# SELECT xmin, xmax, * FROM seq_table; xmin | xmax | seq_number | query_number -------+------+------------+-------------- 21675 | 0 | 1 | Query1 (以下省略)
通常、マスタとスレーブでトランザクションIDは一致しない。
CREATE DATABASEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_db2データベースを作成する。
[client]$ psql -h db1
postgres=# CREATE DATABASE test_db2;
CREATE DATABASE
postgres=# \l
List of databases
Name | Owner | Encoding
-----------+----------+----------
postgres | postgres | EUC_JP
template0 | postgres | EUC_JP
template1 | postgres | EUC_JP
test_db | postgres | EUC_JP
test_db2 | postgres | EUC_JP
(5 rows)
クライアントからdb2サーバに接続し、test_db2データベースが作成されているか確認する。
[client]$ psql -h db2
postgres=# \l
List of databases
Name | Owner | Encoding
-----------+----------+----------
postgres | postgres | EUC_JP
template0 | postgres | EUC_JP
template1 | postgres | EUC_JP
test_db | postgres | EUC_JP
(4 rows)
CREATE USERの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_userユーザを作成する。
[client]$ psql -h db1
postgres=# CREATE USER test_user;
CREATE ROLE
postgres=# \du
List of roles
Role name | Superuser | Create role | Create DB | Connections | Member of
-----------+-----------+-------------+-----------+-------------+-----------
postgres | yes | yes | yes | no limit |
test_user | no | no | no | no limit |
(2 rows)
クライアントからdb2サーバに接続し、test_userユーザが作成されているか確認する。
[client]$ psql -h db2
postgres=# \du
List of roles
Role name | Superuser | Create role | Create DB | Connections | Member of
-----------+-----------+-------------+-----------+-------------+-----------
postgres | yes | yes | yes | no limit |
(1 row)
CREATE GROUPの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_groupグループを作成する。
[client]$ psql -h db1
postgres=# CREATE GROUP test_group;
CREATE ROLE
postgres=# \dg
List of roles
Role name | Superuser | Create role | Create DB | Connections | Member of
------------+-----------+-------------+-----------+-------------+-----------
postgres | yes | yes | yes | no limit |
test_group | no | no | no | no limit |
(2 rows)
クライアントからdb2サーバに接続し、test_userグループが作成されているか確認する。
[client]$ psql -h db2
postgres=# \dg
List of roles
Role name | Superuser | Create role | Create DB | Connections | Member of
-----------+-----------+-------------+-----------+-------------+-----------
postgres | yes | yes | yes | no limit |
(1 row)
CREATE SCHEMAの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_schemaスキーマを作成する。
[client]$ psql -h db1
postgres=# CREATE SCHEMA test_schema;
CREATE SCHEMA
postgres=# \dn
List of schemas
Name | Owner
--------------------+----------
information_schema | postgres
pg_catalog | postgres
pg_toast | postgres
public | postgres
test_schema | postgres
(5 rows)
クライアントからdb2サーバに接続し、test_schemaスキーマが作成されているか確認する。
[client]$ psql -h db2
postgres=# \dn
List of schemas
Name | Owner
--------------------+----------
information_schema | postgres
pg_catalog | postgres
pg_toast | postgres
public | postgres
(4 rows)
CREATE TABLEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_tableテーブルを作成する。
[client]$ psql -h db1
postgres=# CREATE TABLE test_table(i INTEGER);
CREATE TABLE
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+------------+-------+----------
public | test_table | table | postgres
(1 row)
クライアントからdb2サーバに接続し、test_tableテーブルが作成されているか確認する。
[client]$ psql -h db2 postgres=# \dt No relations found.
CREATE TABLE ASの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_table2テーブルを作成する。
[client]$ psql -h db1
postgres=# CREATE TABLE test_table(i INTEGER);
CREATE TABLE
postgres=# CREATE TABLE test_table2 AS SELECT * FROM test_table;
SELECT
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+----------
public | test_table | table | postgres
public | test_table2 | table | postgres
(2 rows)
クライアントからdb2サーバに接続し、test_table2テーブルが作成されているか確認する。
[client]$ psql -h db2 postgres=# \dt No relations found.
CREATE TEMP TABLEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_temptableテーブルを作成する。
[client]$ psql -h db1
postgres=# CREATE TABLE test_table(i INTEGER);
CREATE TABLE
postgres=# CREATE TEMP TABLE test_temptable AS SELECT * FROM test_table;
SELECT
postgres=# \dt
List of relations
Schema | Name | Type | Owner
-----------+----------------+-------+----------
pg_temp_7 | test_temptable | table | postgres
public | test_table | table | postgres
(2 rows)
クライアントからdb2サーバに接続し、test_temptableテーブルが作成されているか確認する。
[client]$ psql -h db2 postgres=# \dt No relations found.
CREATE TABLESPACEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_tablespaceテーブルスペースを作成する。
[db1/db2]$ mkdir /tmp/test_tablespace
[client]$ psql -h db1
postgres=# CREATE TABLESPACE test_tablespace LOCATION '/tmp/test_tablespace';
CREATE TABLESPACE
postgres=# \db
List of tablespaces
Name | Owner | Location
-----------------+----------+----------------------
pg_default | postgres |
pg_global | postgres |
test_tablespace | postgres | /tmp/test_tablespace
(3 rows)
クライアントからdb2サーバに接続し、test_tablespaceテーブルスペースが作成されているか確認する。
[client]$ psql -h db2
postgres=# \db
List of tablespaces
Name | Owner | Location
------------+----------+----------
pg_default | postgres |
pg_global | postgres |
(2 rows)
CREATE SEQUENCEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_seqシーケンスを作成する。
[client]$ psql -h db1
postgres=# CREATE SEQUENCE test_seq;
CREATE SEQUENCE
postgres=# \ds
List of relations
Schema | Name | Type | Owner
--------+----------+----------+----------
public | test_seq | sequence | postgres
(1 row)
クライアントからdb2サーバに接続し、test_seqシーケンスが作成されているか確認する。
[client]$ psql -h db2 postgres=# \ds No relations found.
CREATE DOMAINの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_domainドメインを作成する。
[client]$ psql -h db1
postgres=# CREATE DOMAIN post_code AS CHARACTER (8)
postgres-# CONSTRAINT post_code_must_be_7_digits
postgres-# CHECK (VALUE ~ '~\\d{3}-\\d[4]$');
CREATE DOMAIN
postgres=# \dD
List of domains
Schema | Name | Type | Modifier | Check
--------+-----------+--------------+----------+------------------------------------------
public | post_code | character(8) | | CHECK (VALUE ~ E'~\\d{3}-\\d[4]$'::text)
(1 row)
クライアントからdb2サーバに接続し、test_domainドメインが作成されているか確認する。
[client]$ psql -h db2
postgres=# \dD
List of domains
Schema | Name | Type | Modifier | Check
--------+------+------+----------+-------
(0 rows)
CREATE VIEWの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_viewヴューを作成する。
[client]$ psql -h db1
postgres=# CREATE VIEW test_view AS SELECT i AS number FROM test_table;
CREATE VIEW
postgres=# \dv
List of relations
Schema | Name | Type | Owner
--------+-----------+------+----------
public | test_view | view | postgres
(1 row)
クライアントからdb2サーバに接続し、test_viewヴューが作成されているか確認する。
[client]$ psql -h db2 postgres=# \dv No relations found.
CREATE INDEXの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_indexインデックスを作成する。
[client]$ psql -h db1
postgres=# CREATE TABLE test_table(i INTEGER);
CREATE TABLE
postgres=# CREATE UNIQUE INDEX test_idx on test_table (i);
CREATE INDEX
postgres=# \di
List of relations
Schema | Name | Type | Owner | Table
--------+----------+-------+----------+------------
public | test_idx | index | postgres | test_table
(1 row)
クライアントからdb2サーバに接続し、test_indexインデックスが作成されているか確認する。
[client]$ psql -h db2 postgres=# \di No relations found.
CREATE RULEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_table_logテーブルとtest_ruleルールを作成する。
[client]$ psql -h db1
postgres=# CREATE TABLE test_table_log (user_name TEXT, acttime TIMESTAMP);
CREATE TABLE
postgres=# CREATE RULE test_rule AS ON INSERT TO test_table
postgres-# DO INSERT INTO test_table_log VALUES (CURRENT_USER, CURRENT_TIMESTAMP);
CREATE RULE
postgres=# INSERT INTO test_table VALUES (1);
INSERT 0 1
postgres=# SELECT * FROM pg_rules WHERE tablename = 'test_table';
-[ RECORD 1 ]-----------------------------------------------------------------------------
--------------------------------------------------------
schemaname | public
tablename | test_table
rulename | test_rule
definition | CREATE RULE test_rule AS ON INSERT TO test_table DO INSERT INTO
test_table_log (user_name, acttime) VALUES ("current_user"(), now());
postgres=# SELECT * FROM test_table_log;
-[ RECORD 1 ]-------------------------
user_name | postgres
acttime | 2006-12-08 13:38:55.903292
クライアントからdb2サーバに接続し、test_table_logテーブルとtest_ruleルールが作成されているか確認する。
[client]$ psql -h db2 postgres=# SELECT * FROM pg_rules WHERE tablename = 'test_table'; schemaname | tablename | rulename | definition ------------+-----------+----------+------------ (0 rows) postgres=# SELECT * FROM test_table_log; ERROR: relation "test_table_log" does not exist ERROR: relation "test_table_log" does not exist
CREATE LANGUAGEの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、plpgsql言語を登録する。
[client]$ psql -h db1 postgres=# CREATE LANGUAGE plpgsql; CREATE LANGUAGE postgres=# SELECT * FROM pg_language WHERE lanname = 'plpgsql'; lanname | lanispl | lanpltrusted | lanplcallfoid | lanvalidator | lanacl ---------+---------+--------------+---------------+--------------+-------- plpgsql | t | t | 16767 | 16768 | (1 row)
クライアントからdb2サーバに接続し、plpgsql言語が登録されているか確認する。
[client]$ psql -h db2 postgres=# SELECT * FROM pg_language WHERE lanname = 'plpgsql'; lanname | lanispl | lanpltrusted | lanplcallfoid | lanvalidator | lanacl ---------+---------+--------------+---------------+--------------+-------- (0 rows)
CREATE FUNCTIONの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、log_function関数を作成する。
[client]$ psql -h db1
postgres=# CREATE FUNCTION log_function() RETURNS TRIGGER AS '
postgres'# BEGIN
postgres'# INSERT INTO test_table_log VALUES (
postgres'# CURRENT_USER, CURRENT_TIMESTAMP);
postgres'# RETURN NEW;
postgres'# END;
postgres'# ' LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# \df log_function
List of functions
Schema | Name | Result data type | Argument data types
--------+--------------+------------------+---------------------
public | log_function | "trigger" |
(1 row)
クライアントからdb2サーバに接続し、log_function関数が作成されているか確認する。
[client]$ psql -h db2
postgres=# \df log_function
List of functions
Schema | Name | Result data type | Argument data types
--------+------+------------------+---------------------
(0 rows)
CREATE TRIGGERの実行結果がレプリケーションされるか検証する。
クライアントからdb1サーバに接続し、test_triggerトリガを作成する。
[client]$ psql -h db1 postgres=# CREATE TRIGGER test_trigger AFTER UPDATE ON test_table FOR EACH ROW EXECUTE PROCEDURE log_function(); CREATE TRIGGER postgres=# SELECT * FROM pg_trigger WHERE tgname = 'test_trigger'; -[ RECORD 1 ]--+------------- tgrelid | 16750 tgname | test_trigger tgfoid | 16772 tgtype | 17 tgenabled | t tgisconstraint | f tgconstrname | tgconstrrelid | 0 tgdeferrable | f tginitdeferred | f tgnargs | 0 tgattr | tgargs |
クライアントからdb2サーバに接続し、log_function関数が作成されているか確認する。
[client]$ psql -h db2 postgres=# SELECT * FROM pg_trigger WHERE tgname = 'test_trigger'; (No rows)
ラージオブジェクトがレプリケーションされるか検証する。
クライアントからマスタのtest_dbデータベースに接続し、tmpディレクトリにあるPostgreSQL 8.1.5のソースコードアーカイブを、ラージオブジェクトとして登録する。そして、ラージオブジェクトの登録状況とそれが取得できることを確認する。
[client]$ psql -h db1 test_db
test_db=# \lo_import '/tmp/postgresql-8.1.5.tar.gz' 'PostgreSQL archive'
lo_import 16745
test_db=# \lo_list
Large objects
ID | Description
-------+-------------
16745 | ls command
(1 row)
test_db=# \lo_export 16745 '/tmp/postgresql-8.1.5.tar.gz'
lo_export
クライアントからスレーブのtest_dbデータベースに接続し、ラージオブジェクトの登録状況とそれが取得できるか確認する。取得時はラージオブジェクトのOIDは登録時のOIDを使用する。
[client]$ psql -h db2 test_db test_db=# \lo_list Large objects ID | Description ----+------------- (0 rows) test_db=# \lo_export 16745 '/tmp/ls_command' could not open large object 16745
クライアント上で下記のコマンドを実行する。
[client]$ pgbench -h db1 -c 10 -t 1000 test_db
pgbenchの実行中にdb1サーバ上で下記のコマンドを実行し、slonプロセスを強制終了する。そして、その後もpgbenchが動き続け、正常終了することを確認する。
[db1]$ killall -INT slon
pgbenchが終了後、クライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異があることを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
db1サーバ上でslonを起動する。
[db1]$ slon slony_test "dbname=test_db user=postgres host=db1" &
少し間をおいてからクライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異がないことを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
クライアント上で下記のコマンドを実行する。
[client]$ pgbench -h db1 -c 10 -t 1000 test_db
pgbenchの実行中にdb2サーバ上で下記のコマンドを実行し、slonプロセスを強制終了する。そして、その後もpgbenchが動き続け、正常終了することを確認する。
[db2]$ killall -INT slon
pgbenchが終了後、クライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異があることを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
db2サーバ上でslonを起動する。
[db2]$ slon slony_test "dbname=test_db user=postgres host=db2" &
少し間をおいてからクライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異がないことを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
クライアント上で下記のコマンドを実行する。
[client]$ pgbench -h db1 -c 10 -t 1000 test_db
pgbenchの実行中にdb1サーバ上で下記のコマンドを実行し、postmasterプロセスを強制終了する。そして、pgbenchも同時に終了することを確認する。
[db1]$ killall -INT postmaster
db1サーバ上でpostmasterを起動する。
[db1]$ pg_ctl -w start
クライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異があることを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
db1サーバ上でslonを起動する。
[db1]$ slon slony_test "dbname=test_db user=postgres host=db2" &
少し間をおいてからクライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異がないことを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
クライアント上で下記のコマンドを実行する。
[client]$ pgbench -h db1 -c 10 -t 1000 test_db
pgbenchの実行中にdb2サーバ上で下記のコマンドを実行し、postmasterプロセスを強制終了する。そして、その後もpgbenchが動き続け、正常終了することを確認する。
[db2]$ killall -INT postmaster
pgbenchが終了後、db2サーバ上でpostmasterを起動する。
[db2]$ pg_ctl -w start
クライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異があることを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
db2サーバ上でpostmasterを起動する。
[db2]$ pg_ctl -w start
db2サーバ上でslonを起動する。
[db2]$ slon slony_test "dbname=test_db user=postgres host=db2" &
少し間をおいてからクライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異がないことを確認する。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
クライアント上で下記のコマンドを実行する。
[client]$ pgbench -h db1 -c 10 -t 1000 test_db
pgbenchの実行中にdb1サーバ上で下記のコマンドを実行し、ネットワークインタフェースをダウンさせる。今回はdb1サーバをリモートで操作しているため、atコマンドを使い5分後にネットワークインタフェースをアップする設定も行う。そして、その後もpgbenchが動き続け、正常終了することを確認する。
[db1]$ su - [db1]# at now + 5 minutes at> ifconfig eth0 up at>job 3 at 2006-11-20 16:28 [db1]# ifconfig eth0 down [db1]# exit
ネットワークの復旧直後と少し間をおいた後にクライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異があるか確認する。復旧直後は差異があり、少し間をおいた後は差異がないのが正常である。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history
クライアント上で下記のコマンドを実行する。
[client]$ pgbench -h db1 -c 10 -t 1000 test_db
pgbenchの実行中にdb2サーバ上で下記のコマンドを実行し、ネットワークインタフェースをダウンさせる。今回はdb2サーバをリモートで操作しているため、atコマンドを使い5分後にネットワークインタフェースをアップする設定も行う。そして、その後もpgbenchが動き続け、正常終了することを確認する。
[db2]$ su - [db2]# at now + 5 minutes at> ifconfig eth0 up at>job 3 at 2006-11-20 17:51 [db2]# ifconfig eth0 down [db2]# exit
ネットワークの復旧直後と少し間をおいた後にクライアント上でpgdiff.shを実行し、マスタとスレーブのtest_dbデータベースの各テーブルの内容に差異があるか確認する。復旧直後は差異があり、少し間をおいた後は差異がないのが正常である。
[client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid accounts [client]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol bid branches [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol tid tellers [cleint]$ ./pgdiff.sh --mhost db1 --shost db2 --database test_db --sortcol aid bid tid delta history