PostgreSQL pg_wal archive保存期間設定について

# 概要
pg_walアーカイブは、PostgreSQL側で一定期間の保存設定を行わないと増え続け、ディスクの空き容量を圧迫してしまいます。その結果、ハードウェアコストが無駄になる可能性がありますので、保存期間の設定が必要です。その保存期間設定方法を紹介します
# pg_wal archive保存期間設定方法
#### 方法①

backup solutionの定期バックアップ（例：daily backup batch)により、過去pg_wal archiveを削除する

例：pg_rmanの場合、pg_rman.iniのKEEP_ARCLOG_DAYS=[n]の設定より削除
```
pg_rman.ini

ARCLOG_PATH='/home/postgres/arc'
SRVLOG_PATH='/home/postgres/pghome/logs'

KEEP_DATA_GENERATIONS=1
KEEP_ARCLOG_DAYS=1
```

この方法ではバッチ処理によって過去のpg_walアーカイブを削除するため、例えば、デイリーバックアップバッチの場合、KEEP_ARCLOG_DAYS=1に設定していても、実際には最大で2日分のpg_walアーカイブが保存されることになります。そのため、ディスクのサイズを見積もる際には注意が必要です。
#### 方法②
自作のシェルスクリプトを使用して、過去のpg_walアーカイブを削除することができます。

PostgreSQLには、MySQLのbinlog_expire_logs_secondsのようにリアルタイムでpg_walアーカイブを削除するためのパラメータはありませんが、自作のスクリプトを使うことで、リアルタイムでのpg_walアーカイブ削除を実現することが可能です。

# pg_wal 過去archiveのリアルタイム削除方法
pg_wal archiveのshell scriptを開発して、$PG_HOME/binに配置

例：pg_archivelog.sh
```
#!/bin/sh
 
V_ARC_PATH=$PG_HOME/arc
V_PGDATA=$PG_HOME/data
V_ARCHIVE_LOGFILE=$PG_HOME/logs/archive_err.log
 
 
V_SOURCE_ARC=$1
V_TARGET_ARC=$2.arc
V_DURATION=$3
 
 
function Usage() {
        date +"%Y/%m/%d %H:%M:%S" >> $V_ARCHIVE_LOGFILE
        echo "Usage:sh $PG_HOME/bin/pg_archivelog.sh %p %f <DURATION> " >> $V_ARCHIVE_LOGFILE
        echo "Sample:sh $PG_HOME/bin/pg_archivelog.sh %p %f 1440 " >> $V_ARCHIVE_LOGFILE
        exit 1
}
 
if [ -z "$V_SOURCE_ARC" ]; then
        Usage;
fi
 
if [ -z "$V_TARGET_ARC" ]; then
        Usage;
fi
 
if [ -z "$V_DURATION" ]; then
        Usage;
fi
 
cp $V_PGDATA/$V_SOURCE_ARC $V_ARC_PATH/$V_TARGET_ARC
 
find -L $V_ARC_PATH -type f -name '0000000*.arc' -mmin +$V_DURATION | grep -v '*.history' |  xargs rm -f
 
exit 0
```
postgresql.confのarchive_commandパラメータは下記のように設定する
```
archive_command = 'sh $PG_HOME/bin/pg_archivelog.sh %p %f 1440 '
```
新しいpg_walがアーカイブされるたびに、設定された保存期間より古いpg_walアーカイブが自動的に削除されることで、常に設定された期間分のpg_walアーカイブが保存されるようになります。

#### 保存期間のONLINE変更方法：

例えば、負荷テストや大量データのロード時にpg_walアーカイブの保存期間を短縮したい場合、以下のように設定を変更することができます。

例: 保存期間を1日から1時間に短縮する


```
view $PG_HOME/data/postgresql.conf
AS-IS：
archive_command = 'sh $PG_HOME/bin/pg_archivelog.sh %p %f 1440 '
TO-BE：
archive_command = 'sh $PG_HOME/bin/pg_archivelog.sh %p %f 60 '
 
psqlで即時変更反映させる
psql> select pg_reload_conf();
psql> exit
```

# 自作pg_wal archive scriptの活用
自作pg_wal archive scirptはいつくか活用ができます。
例：下記の二つユースケースを紹介します
1, pg_wal archiveの非圧縮/圧縮の設定変更する
2, disk usage > 80%の場合、pg_walの保存期間を自動短縮することにより、disk fullを防ぎます。

pg_archivelog.shは下記のように非圧縮/圧縮のパラメータ及びdiskusage>80%の自動処理を追加します
```
################################################
## For postgresql pg_wal archive-command      ##
## 2025/02/20                                 ##
################################################
#!/bin/sh
 
V_ARC_PATH=$PGHOME/arc
V_PGDATA=$PGHOME/data
V_ARCHIVE_LOGFILE=$PGHOME/logs/archive_err.log
 
 
V_SOURCE_ARC=$1
V_TARGET_ARC=$2.arc
V_DURATION=$3
V_COMPRESS=$4
 
function Usage() {
        date +"%Y/%m/%d %H:%M:%S" >> $V_ARCHIVE_LOGFILE
        echo "Usage:sh $PGHOME/bin/pg_archivelog.sh %p %f <DURATION> <COMPRESS | NOCOMPRESS>" >> $V_ARCHIVE_LOGFILE
        echo "Sample:sh $PGHOME/bin/pg_archivelog.sh %p %f 1440 COMPRESS" >> $V_ARCHIVE_LOGFILE
        echo "Sample:sh $PGHOME/bin/pg_archivelog.sh %p %f 60 NOCOMPRESS" >> $V_ARCHIVE_LOGFILE
        exit 1
}
 
if [ -z "$V_SOURCE_ARC" ]; then
        Usage;
fi
 
if [ -z "$V_TARGET_ARC" ]; then
        Usage;
fi
 
if [ -z "$V_DURATION" ]; then
        Usage;
fi
if [ -z "$V_COMPRESS" ]; then
        Usage;
fi
 
if [ $V_COMPRESS = 'COMPRESS' ]; then
        zip $V_ARC_PATH/$V_TARGET_ARC.zip $V_PGDATA/$V_SOURCE_ARC
        find -L $V_ARC_PATH -type f -name '0000000*.arc.zip' -mmin +$V_DURATION | grep -v '*.history' | xargs rm -f
 
        V_USAGERATE=`df -a "$V_ARC_PATH" | grep '/' |  awk '{print $5}' | head -n 1 |cut -d '%' -f 1`
        if [ $V_USAGERATE -gt 80 ] ; then
                find -L $V_ARC_PATH -type f -name '0000000*.zip' -mmin +120 | grep -v '*.history' | xargs rm -f
        fi
else
        cp $V_PGDATA/$V_SOURCE_ARC $V_ARC_PATH/$V_TARGET_ARC
        find -L $V_ARC_PATH -type f -name '0000000*.arc' -mmin +$V_DURATION | grep -v '*.history' |  xargs rm -f
 
        V_USAGERATE=`df -a "$V_ARC_PATH" | grep '/' |  awk '{print $5}' | head -n 1 |cut -d '%' -f 1`
        if [ $V_USAGERATE -gt 80 ] ; then
                find -L $V_ARC_PATH -type f -name '0000000*.arc' -mmin +120 | grep -v '*.history' | xargs rm -f
        fi
fi
 
exit 0
```
postgresql.confのarchive_commandパラメータ設定
```
archive_command = 'sh $PG_HOME/bin/pg_archivelog.sh %p %f 1440 NOCOMPRESS'
```
圧縮変更したい場合、下記のようにONLINEで圧縮変更可能です
```
view $PG_HOME/data/postgresql.conf
AS-IS：
archive_command = 'sh $PG_HOME/bin/pg_archivelog.sh %p %f 1440 NOCOMPRESS'
TO-BE：
archive_command = 'sh $PG_HOME/bin/pg_archivelog.sh %p %f 1440 COMPRESS'
 
# psqlで変更反映
psql> select pg_reload_conf();
psql> exit
```