PostgreSQLのデータベースクラスタ内のサブディレクトリや設定ファイルの役割（5、pg_dynshmemの役割）

##はじめに
Dockerを使ってPostgreSQLのデータべースクラスタのサブディレクトリ・設定ファイルの役割を理解するのが目的です

##使用コンテナ
・postgres:11-alpin

PostgreSQLのデータベースクラスタのディレクトリ構成は下記のような構造になっています。

```bash
$ tree -L 1
data
├── PG_VERSION 
├── base          #データベースごとのサブディレクトリを保有するサブディレクトリ
├── global        #pg_databaseのようなクラスタで共有するテーブルを保有するサブディレクトリ
├── pg_commit_ts  #トランザクションのコミット時刻のデータを保有するサブディレクトリ
├── pg_dynshmem   #動的共有メモリサブシステムで使われるファイルを保有するサブディレクトリ
├── pg_hba.conf   #PostgreSQL に接続するクライアントの認証に関する設定を記述するファイル
├── pg_ident.conf #Ident認証のユーザー名をPostgreSQLのロール名にマッピングするためのファイル
├── pg_logical    #論理デコードのための状態データを保有するサブディレクトリ
├── pg_multixact  #マルチトランザクション状態のデータを保有するサブディレクトリ（共有行ロックで使用される）
├── pg_notify     #LISTEN/NOTIFY状態データを保有するサブディレクトリ
├── pg_replslot   #レプリケーションスロットデータを保有するサブディレクトリ
├── pg_serial     #コミットされたシリアライザブルトランザクションに関する情報を保有するサブディレクトリ
├── pg_snapshots  #エキスポートされたスナップショットを保有するサブディレクトリ
├── pg_stat       #統計サブシステム用の永続ファイルを保有するサブディレクトリ
├── pg_stat_tmp   #統計サブシステム用の一時ファイルを保有するサブディレクトリ
├── pg_subtrans   #サブトランザクションの状態のデータを保有するサブディレクトリ
├── pg_tblspc     #テーブル空間へのシンボリックリンクを保有するサブディレクトリ
├── pg_twophase   #プリペアドトランザクション用の状態ファイルを保有するサブディレクトリ
├── pg_wal        #WAL（ログ先行書き込み）ファイルを保有するサブディレクトリ
├── pg_xact       #トランザクションのコミット状態のデータを保有するサブディレクトリ  
├── postgresql.auto.conf #ALTER SYSTEMにより設定された設定パラメータを格納するのに使われるファイル
├── postgresql.conf #PostgreSQLのパラメータを設定するファイル
├── postmaster.opts #最後にサーバを起動した時のコマンドラインオプションを記録するファイル
└── postmaster.pid  #現在のpostmasterプロセスID（PID）、クラスタのデータディレクトリパス、postmaster起動時のタイムスタンプ、ポート番号、共有メモリのセグメントIDを記録するロックファイル
```

##pg_dynshmemの役割
**動的共有メモリサブシステムで使われるファイルを保有するサブディレクトリ**となっています
ここでは動的共有メモリサブシステムについては詳細は省くが、pg_dynshmemは共有メモリを表すディレクトリと理解していただければと思います。
共有メモリはプロセス間通信における技法の一つで、DBにおいては並列処理を行う際などに、複数のプロセス間で共有するファイルを共有メモリに置くことで、コピーオンライトと言う機構を用いて、それぞれのプロセスのためにファイルを複製することなく処理を進めさせるためのものです。
つまり、通信を行う2つのプロセスが存在した場合に、プロセス間で共有するファイルがpg_dynshmemのディレクトリにマッピングされるということです。
このpg_dynshmemディレクトリが使用されるのは、dynamic_shared_memory_typeの値がmmapの時に使用されます。


####pg_dynshmemを中身を確認しましょう
```bash
#pg_commit_tsの中身を確認します
$ ls /var/lib/postgresql/data/pg_dynshmem
#空だったため、出力ありませんでした。
```

このpg_dycshmemにファイルをマップするためには
pg_commit_tsと同様に、設定ファイルに変更を加える必要があります。
```bash
$ vi /var/lib/postgresql/data/postgresql.conf
```

テキストエディタでpostgresqlの設定ファイルの下記項目の値をposixからmmapに変更します

```
dynamic_shared_memory_type = posix
↓
dynamic_shared_memory_type = mmap       # the default is the first option
                                        # supported by the operating system:   
                                        #   posix                              
                                        #   sysv
                                        #   windows
                                        #   mmap                      
                                        # use none to disable dynamic shared memory
                                        # (change requires restart)
```

設定を変更後、dockerのrestartをして、postgresサーバーを再立ち上げします。
（※設定ファイルの再読み込みでは変更されません）

dockerのリスタートが終わって、pg_dynshmemの中身を確認すると

```bash
$ ls /var/lib/postgresql/data/pg_dynshmem
mmap.2098738232
```

と言うmmapによるマッピング領域ができています。
公式ドキュメントには下記のような注意書きがあり、使用する場面はかなり限定的なものと思われます。

*どのプラットフォームでもデフォルトになっていないmmapは、オペレーティングシステムが変更されたページをディスクに継続的に書き込み、I/O負荷を増加させるので一般的には利用が推奨されていません。 しかし、デバッグ目的のためにpg_dynshmemディスクがRAMディスク上にある場合や、他の共有メモリ機能が使えない場合は有用かもしれません。*

##終わりに
今回のように、PostgresSQLへの操作がデータベースクラスタへどう変化を起こすかを見て行けたらと思います。

[１、ディレクトリ構造を確認](https://qiita.com/michi-michi/items/0aac8b6ccdb365269c90)
[２、PG_VERSION、baseの役割](https://qiita.com/drafts/dd33d3e1e831d0d79b35/)
[３、globalの役割](https://qiita.com/michi-michi/items/c3ca6b1efe13e3a3af84)
[4、pg_commit_tsの役割](https://qiita.com/michi-michi/items/dc9ca80a12aa58be3cd1)
5、pg_dynshmemの役割