[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コマンドで保存するというようなこともあるようなので。
私はこの点を最初に見た時に、かなり驚きました。
ちなみにディレクトリ構造を示すと以下のようになります。
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つ以上のデータベースクラスタを同時に実行する
ことは可能なのか確認してみることにする。
まず、既存のクラスタが稼働していることを確認する。
[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をしてあげること!
これをしないと、余計な操作が増えてうんざりしそうですね。