見出し画像

[PostgreSQL]DBクラスタとpg_ctlコマンド周りの考え方をざっくり理解した[02]

どーも。
しょうです。

PostgreSQLについては前回、CentOS7上にインストールと
環境変数PATHを通しました。
以下その記事になります。もし興味ある方がいればご覧ください。


最近OSS-DB Silverの学習を通じてDBについて理解を深めようと
しています。
理由は単純で『技術をもっと知りたい』からですね。
専門分野に特化するのもかっこいいのですし憧れますが、
私は知らない部分があると痒くなってくるタイプの変人なので・・・汗

まあ自分の話はそれくらいにして、
この記事の目次は以下になります。



1.データベースクラスタとは何か

私も含め、PostgreSQLを触ったことが無い人からすると
データベースクラスタという表現は少し見慣れない用語かもしれません。
それはもっともな感想で、PostgreSQL独自の用語みたいです。


OSS-DB資格試験を実施しているLPI-JAPANには以下の様に書かれています。

1つのサーバインスタンスによって管理されるデータベースの集合体を
意味します。データベースクラスタ内のデータベースは、それぞれ
テーブルや関数などのオブジェクトを独立して管理します。
一方で、ユーザ情報(ユーザ名、パスワードなど)は、
データベースクラスタ内のグローバルオブジェクトとして管理されている
ため、すべてのデータベースで共通となります。

引用:LPI-JAPAN オススメ!OSS-DB情報 第18回


難しく書いている感じがしますが、
『データベースクラスタの中にはデータベースそのものと、ユーザ情報
等が管理されている領域があるんだな』

みたいなことを押さえられればとりあえず良い気がします。


細かい話は学習の最後の方にやればいいのです。
まず初学者がやるべきことは概要をザっと抑えること。


ちなみにデータベースクラスタはディレクトリ構造です。
Webサーバ(ApacheやNGINX)、DNSサーバ、メールサーバとかと
仕組みはあまり変わらないと思って頂いて問題無いと思います。

DBサーバと聞くと何か特殊な技術を使っているのではないか。
と思われてしまうかもしれませんが、どうやらPostgreSQLについては
そのようなことはないようです。
現にPostgreSQLのデータバックアップの方法としてディレクトリ自体を
cpコマンドで保存するというようなこともあるようなので。

私はこの点を最初に見た時に、かなり驚きました。


ちなみにディレクトリ構造を示すと以下のようになります。

PostgreSQL-ページ3

icon used from icons8
figure created by draw.io

後程紹介しますが、initdbコマンドを作ってデータベースクラスタを
作成することになるのですが、上記の場合では/home/postgres/data/配下に
データベースクラスタを作成していることになりますね。

この記事で覚えておきたいディレクトリはbase/とlog/です。

base/配下にはデータベースを作成するときに使用するTemplete0,1及び
initdbコマンドを実行したユーザと同じ名前のデータベースが作成されます。

log/配下にはエラーログ等が作成されます。
後程実験でこのディレクトリを確認しに行きます。



2.データベースクラスタを起動してみよう

データベースクラスタを作成するためのコマンドは以下のようになります。
※下記は一例です。各自の環境に合わせて調整してください。

initdb --encoding=UTF8 --no-locale /home/postgres/data/ 

上記は/home/postgresql/data/配下に日本語対応可能なデータベースクラスタを作成します。
データベースで日本語を使用したい場合、encodingをUTF-8にして
ロケールをno、またはCを指定してあげる必要があるようです。

ちなみにロケールとは『システムやソフトウェアにおける言語や国・地域の設定のこと』を示す用です。


では早速、作成した環境でinitdbを実行してみたいと思います。
実行した結果のログを以下に記載します。
このように初期作成の際に色々設定をしてくれているようです。
またログの最後の方にはどのようにしてこのデータベースクラスタを
起動するかが書いていますね。

[postgres@ssh_server data]$ initdb --encoding=UTF8 --no-locale /home/postgres/data/ 
データベースシステム内のファイルの所有者はユーザ"postgres"となります。 
このユーザをサーバプロセスの所有者とする必要があります。 
データベースクラスタはロケール"C"で初期化されます。 
デフォルトのテキスト検索構成は english に設定されます。 
データベージのチェックサムは無効です。 
ディレクトリ/home/postgres/dataの権限を設定しています ... ok 
サブディレクトリを作成しています ... ok 
動的共有メモリの実装を選択しています ... posix 
デフォルトのmax_connectionsを選択しています ... 100 
デフォルトのshared_buffersを選択しています ... 128MB 
デフォルトの時間帯を選択しています ... Asia/Tokyo 
設定ファイルを
システムやソフトウェアにおける言語や国・地域の設定のことをこのように呼ぶ。
作成しています ... ok 
ブートストラップスクリプトを実行しています ... ok 
ブートストラップ後の初期化を実行しています ... ok 
データをディスクに同期しています ... ok 
initdb: 警告: ローカル接続に対して"trust"認証を有効にします 
pg_hba.confを編集する、もしくは、次回initdbを実行する時に -A オプション、 
あるいは --auth-local および --auth-host オプションを使用することで変更する 
ことがきます。 
成功しました。以下のようにしてデータベースサーバを起動することができます: 
   pg_ctl -D /home/postgres/data/ -l ログファイル start


クラスタを作成した後、ディレクトリを見てみると、
様々なディレクトリ・ファイルが作成されていることが分かります。

[postgres@ssh_server data]$ ls 
PG_VERSION    pg_dynshmem    pg_multixact  pg_snapshots  pg_tblspc    postgresql.auto.conf 
base          pg_hba.conf    pg_notify     pg_stat       pg_twophase  postgresql.conf 
global        pg_ident.conf  pg_replslot   pg_stat_tmp   pg_wal 
pg_commit_ts  pg_logical     pg_serial     pg_subtrans   pg_xact



3.pg_ctlコマンド群について

pg_ctlというのはデータベースクラスタの起動・再起動・停止・確認等を
行う事が出来るコマンドです。
pg_ctlの後にstartとかstopとかを指定して-D (データベースクラスタのフルパス)
という風にコマンドを打ってあげると良いかなという印象です。
systemctlを知っている方はそれに近い操作感だと思ってもらえれば。。。

上記の他にも色々あるのですが、細かいことはその時に覚えます。
いきなり細かいことを覚えようとするとやる気がそがれるので汗

ちなみに
start:データベースクラスタを起動
stop:データベースクラスタを停止
restart:データベースクラスタを再起動
reload:データベースクラスタの設定ファイルの再読み込み
status:データベースクラスタの状態を確認。

です!


1つずつコマンドの実行と出力結果を見てみましょう。

●start

[postgres@ssh_server ~]$ pg_ctl start -D /home/postgres/data/ 
サーバの起動完了を待っています....2021-04-21 17:13:58.298 JST [11969] LOG:  redirecting log output to logging collector process 
2021-04-21 17:13:58.298 JST [11969] HINT:  Future log output will appear in directory "log". 
完了 
サーバ起動完了

●status

[postgres@ssh_server ~]$ pg_ctl status -D /home/postgres/data/ 
pg_ctl: サーバが動作中です(PID: 11969) 
/usr/pgsql-13/bin/postgres "-D" "/home/postgres/data"

●restart

[postgres@ssh_server ~]$ pg_ctl restart -D /home/postgres/data/ 
サーバ停止処理の完了を待っています....完了 
サーバは停止しました 
サーバの起動完了を待っています....2021-04-23 20:43:19.195 JST [2132] LOG:  redirecting log output to logging collector process 
2021-04-23 20:43:19.195 JST [2132] HINT:  Future log output will appear in directory "log". 
完了 
サーバ起動完了 

●reload

[postgres@ssh_server ~]$ pg_ctl reload -D /home/postgres/data/ 
サーバにシグナルを送信しました 

●stop

[postgres@ssh_server log]$ pg_ctl stop -D /home/postgres/data/ -m f 
サーバ停止処理の完了を待っています....完了 
サーバは停止しました 

[postgres@ssh_server log]$ pg_ctl status -D /home/postgres/data/ 
pg_ctl: サーバが動作していません




4.実験①_データベーステーブルを起動したままサーバを停止して時の挙動とその対応

結論から先に記載すると、PostgreSQLのデータベースクラスタを起動
されたままの状態で(PostgreSQLの)ホストOSを停止すると、
PostgreSQLが使用するポートが変に占有された状態になる。

以下はデータベースクラスタを稼働させたまま、わざとrebootを行い、
ホストOSの電源を入れなおした後のpg_ctl statusとstartの実行結果です。
statusでクラスタが起動していないことを確認した後に、
startでクラスタを稼働させようとしてもエラーではじかれて起動できません

[postgres@ssh_server ~]$ pg_ctl status -D /home/postgres/data/ 
pg_ctl: サーバが動作していません 

[postgres@ssh_server ~]$ pg_ctl start -D /home/postgres/data/ 
サーバの起動完了を待っています....2021-04-23 17:55:43.966 JST [1404] LOG:  redirecting log output to logging collector process 
2021-04-23 17:55:43.966 JST [1404] HINT:  Future log output will appear in directory "log". 
待機処理が停止されました 
pg_ctl: サーバを起動できませんでした。 
ログ出力を確認してください。


出力された内容を見てみると「logにアウトプットしているよ!」
ということが書かれているので、そのログを見てみましょう。
logはデータベースクラスタのlog/配下に作成されます。

今回の結果を見てみると、
「 Is another postmaster already running on port 5432? If not, wait a few seconds and retry. 」
という記載があることからポートをすでに使っていることによる
エラーであることが確認出来ます。

[postgres@ssh_server data]$ ls 
PG_VERSION        log           pg_ident.conf  pg_replslot   pg_stat_tmp  pg_wal 
base              pg_commit_ts  pg_logical     pg_serial     pg_subtrans  pg_xact 
current_logfiles  pg_dynshmem   pg_multixact   pg_snapshots  pg_tblspc    postgresql.auto.conf 
global            pg_hba.conf   pg_notify      pg_stat       pg_twophase  postgresql.conf 

[postgres@ssh_server data]$ cd log/ 

[postgres@ssh_server log]$ ls 
postgresql-Wed.log 

[postgres@ssh_server log]$ cat postgresql-Wed.log 
2021-04-21 16:50:58.065 JST [11746] LOG:  starting PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit 
2021-04-21 16:50:58.073 JST [11746] LOG:  could not bind IPv6 address "::1": Address already in use 
2021-04-21 16:50:58.073 JST [11746] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry. 
2021-04-21 16:50:58.073 JST [11746] LOG:  could not bind IPv4 address "127.0.0.1": Address already in use 
2021-04-21 16:50:58.073 JST [11746] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry. 
2021-04-21 16:50:58.073 JST [11746] WARNING:  could not create listen socket for "localhost" 
2021-04-21 16:50:58.073 JST [11746] FATAL:  could not create any TCP/IP sockets 
2021-04-21 16:50:58.074 JST [11746] LOG:  database system is shut down


では上記のログが本当か、実際に確認してみます。
今回の確認にはlsofコマンドを使いたいと思いますので、
yumでインストールします。

[root@ssh_server ~]# yum -y install lsof 
読み込んだプラグイン:fastestmirror 
Loading mirror speeds from cached hostfile 
* base: ftp.riken.jp 
* extras: ftp.riken.jp 
* updates: ftp.riken.jp 
base                                                                                          | 3.6 kB  00:00:00 
extras                                                                                        | 2.9 kB  00:00:00 
pgdg-common                                                                                   | 2.9 kB  00:00:00 
pgdg10                                                                                        | 3.6 kB  00:00:00 
pgdg11                                                                                        | 3.6 kB  00:00:00 
pgdg12                                                                                        | 3.6 kB  00:00:00 
pgdg13                                                                                        | 3.6 kB  00:00:00 
pgdg95                                                                                        | 3.6 kB  00:00:00 
pgdg96                                                                                        | 3.6 kB  00:00:00 
updates                                                                                       | 2.9 kB  00:00:00 
pgdg-common/7/x86_64/primary_db                                                               | 127 kB  00:00:02 
依存性の解決をしています 
--> トランザクションの確認を実行しています。 
---> パッケージ lsof.x86_64 0:4.87-6.el7 を インストール 
--> 依存性解決を終了しました。 
依存性を解決しました 
===================================================================================================================== 
Package                  アーキテクチャー           バージョン                       リポジトリー              容量 
===================================================================================================================== 
インストール中: 
lsof                     x86_64                     4.87-6.el7                       base                     331 k 
トランザクションの要約 
===================================================================================================================== 
インストール  1 パッケージ 
総ダウンロード容量: 331 k 
インストール容量: 927 k 
Downloading packages: 
警告: /var/cache/yum/x86_64/7/base/packages/lsof-4.87-6.el7.x86_64.rpm: ヘッダー V3 RSA/SHA256 Signature、鍵 ID f4a80eb5: NOKEY 
lsof-4.87-6.el7.x86_64.rpm の公開鍵がインストールされていません 
lsof-4.87-6.el7.x86_64.rpm                                                                    | 331 kB  00:00:00 
file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 から鍵を取得中です。 
Importing GPG key 0xF4A80EB5: 
Userid     : "CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>" 
Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5 
Package    : centos-release-7-8.2003.0.el7.centos.x86_64 (@anaconda) 
From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 
Running transaction check 
Running transaction test 
Transaction test succeeded 
Running transaction 
 インストール中          : lsof-4.87-6.el7.x86_64                                                               1/1 
 検証中                  : lsof-4.87-6.el7.x86_64                                                               1/1 
インストール: 
 lsof.x86_64 0:4.87-6.el7 
完了しました! 


lsofコマンドでポートで実行中のプロセスを確認します。
するとPIDのところに1646と記載されていることが分かります。
なので、このプロセス1646がエラーを引き起こしていることが分かります。

[root@ssh_server ~]# lsof -i:5432 
COMMAND    PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME 
postmaste 1646 postgres    6u  IPv6  24793      0t0  TCP localhost:postgres (LISTEN) 
postmaste 1646 postgres    7u  IPv4  24794      0t0  TCP localhost:postgres (LISTEN)


上記で確認したプロセスをkillした後、再度pg_ctl startを実行することで
データベースクラスタを稼働させることが出来ます。
OSの電源を切ったり、再起動をするときはPostgreSQLを停止した方が
無難そうですね。。。

[root@ssh_server ~]# kill 1646

[postgres@ssh_server ~]$ pg_ctl start -D /home/postgres/data/ 
サーバの起動完了を待っています....2021-04-21 17:13:58.298 JST [11969] LOG:  redirecting log output to logging collector process 
2021-04-21 17:13:58.298 JST [11969] HINT:  Future log output will appear in directory "log". 
完了 
サーバ起動完了

[postgres@ssh_server ~]$ pg_ctl status -D /home/postgres/data/ 
pg_ctl: サーバが動作中です(PID: 11969) 
/usr/pgsql-13/bin/postgres "-D" "/home/postgres/data"



5.実験②_1つのサーバ上に複数のデータベースクラスタを作成し、稼働させる

今までのPostgreSQLの状態は以下のような状態である。

画像2


それでは以下の様に2つ以上のデータベースクラスタを同時に実行する
ことは可能なのか確認してみることにする。

画像3


まず、既存のクラスタが稼働していることを確認する。

[postgres@ssh_server ~]$ pg_ctl status -D /home/postgres/data/ 
pg_ctl: サーバが動作中です(PID: 1450) 
/usr/pgsql-13/bin/postgres "-D" "/home/postgres/data"


次に/home/postgres/配下の現在のディレクトリを確認して
DATA/が無いことを確認して作成する。

[postgres@ssh_server ~]$ pwd 
/home/postgres 

[postgres@ssh_server ~]$ ls -a 
.  ..  .bash_history  .bash_logout  .bash_profile  .bashrc  .psql_history  data 

[postgres@ssh_server ~]$ mkdir DATA 
[postgres@ssh_server ~]$ ls -a 
.  ..  .bash_history  .bash_logout  .bash_profile  .bashrc  .psql_history  DATA  data


次に、最初にデータベースクラスタを作成した時と同じコマンドで
DATA/配下に作れるのか確認してみることにする。
データベースクラスタを複数作成は出来るようだ。

[postgres@ssh_server ~]$ initdb --encoding=UTF8 --no-locale /home/postgres/DATA/ 
データベースシステム内のファイルの所有者はユーザ"postgres"となります。 
このユーザをサーバプロセスの所有者とする必要があります。 
データベースクラスタはロケール"C"で初期化されます。 
デフォルトのテキスト検索構成は english に設定されます。 
データベージのチェックサムは無効です。 
ディレクトリ/home/postgres/DATAの権限を設定しています ... ok 
サブディレクトリを作成しています ... ok 
動的共有メモリの実装を選択しています ... posix 
デフォルトのmax_connectionsを選択しています ... 100 
デフォルトのshared_buffersを選択しています ... 128MB 
デフォルトの時間帯を選択しています ... Asia/Tokyo 
設定ファイルを作成しています ... ok 
ブートストラップスクリプトを実行しています ... ok 
ブートストラップ後の初期化を実行しています ... ok 
データをディスクに同期しています ... ok 
initdb: 警告: ローカル接続に対して"trust"認証を有効にします 
pg_hba.confを編集する、もしくは、次回initdbを実行する時に -A オプション、 
あるいは --auth-local および --auth-host オプションを使用することで変更する 
ことがきます。 
成功しました。以下のようにしてデータベースサーバを起動することができます: 
   pg_ctl -D /home/postgres/DATA/ -l ログファイル start


ではこのデータベースクラスタが稼働出来るか確認してみる。
結論になるが、ログを確認してみると
「ポートをすでに使用している」という理由で稼働出来なかった。
つまりそれぞれのデータベースクラスタで使用しているポートを
変更することが出来れば複数クラスタを同時稼働することも出来る?

[postgres@ssh_server ~]$ pg_ctl start -D /home/postgres/DATA/ 
サーバの起動完了を待っています....2021-04-24 08:08:58.280 JST [1766] LOG:  redirecting log output to logging collector process 
2021-04-24 08:08:58.280 JST [1766] HINT:  Future log output will appear in directory "log". 
待機処理が停止されました 
pg_ctl: サーバを起動できませんでした。 
ログ出力を確認してください。 

[postgres@ssh_server ~]$ pwd 
/home/postgres 
[postgres@ssh_server ~]$ cd DATA/ 
[postgres@ssh_server DATA]$ ls 
PG_VERSION  current_logfiles  log           pg_dynshmem  pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    pg_wal   postgresql.auto.conf 
base        global            pg_commit_ts  pg_hba.conf  pg_logical     pg_notify     pg_serial    pg_stat       pg_subtrans  pg_twophase  pg_xact  postgresql.conf 
[postgres@ssh_server DATA]$ cd log/ 
[postgres@ssh_server log]$ ls 
postgresql-Sat.log 

[postgres@ssh_server log]$ cat postgresql-Sat.log 
2021-04-24 08:08:58.280 JST [1766] LOG:  starting PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit 
2021-04-24 08:08:58.283 JST [1766] LOG:  could not bind IPv6 address "::1": Address already in use 
2021-04-24 08:08:58.283 JST [1766] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry. 
2021-04-24 08:08:58.283 JST [1766] LOG:  could not bind IPv4 address "127.0.0.1": Address already in use 
2021-04-24 08:08:58.283 JST [1766] HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry. 
2021-04-24 08:08:58.283 JST [1766] WARNING:  could not create listen socket for "localhost" 
2021-04-24 08:08:58.283 JST [1766] FATAL:  could not create any TCP/IP sockets 
2021-04-24 08:08:58.285 JST [1766] LOG:  database system is shut down


再度OSS-DB資格試験を実施しているLPI-JAPANの記事を確認してみると、
以下のように書かれている。
つまりポート番号を変えれば複数クラスタは同時に起動出来るということ。

複数のデータベースクラスタを作成する場合、initdb コマンドで作成された postgresql.conf を編集して、port パラメータをデフォルトの5432から変更する必要があることに注意してください。データベースクラスタのディレクトリと、ポート番号を別にすれば、同一マシン上で複数のデータベースクラスタを同時に稼働させることができます。

引用:LPI-JAPAN オススメ!OSS-DB情報 第18回


6.感想

何となくだけど、PostgreSQLの起動や停止の仕方、
気を付けたほうが良いポイント等がわかったかなと思います。

仮想環境でPostgreSQLを試す際は、操作を終了するタイミングで
必ずstopをしてあげること!

これをしないと、余計な操作が増えてうんざりしそうですね。


この記事が気に入ったらサポートをしてみませんか?