📚 Using pg_basebackup to backup & recover the DB¶
🔍 Prepare:¶
## Prepare the DB Environment:
Environment name Version OS version Redhat 7.6 PostgreSQL version 13.4 DB server 10.38.36.110 Database:HQRPAD1 PostgreSQL 16.X Port 5435 Table space path /pgdata/HQRPAD1_tblspc Archive Wal path /pgdata/HQRPAD1_archive
## Prepare parameter on the postgresql.conf file:
parameter name Version archive_command 'cp %p /pgdata/HQRPAD1_archive/%f' restore_command 'cp /pgdata/HQRPAD1_archive/%f %p'
1. Backup PostgreSQL DB(postgres)¶
16384.tar.gz → archive for tablespace base.tar.gz → archive for database pg_wal.tar.gz → archive for wal file
2. Set the cron job to backup DB every day(postgres)¶
- 2.1 Make sure pg_hba.conf got the correct information
echo "host replication postgres 10.38.36.111/32 trust" >> /pgdata/HQRPAD1/pg_hba.conf
more pg_hba.conf |grep postgres
Add server IP in pg_hba.conf
- 2.2 Modify daily backup script(WZS)
### PG Dump backup folder
vim /pgdata/wistron/script/ZSARMP/pgbasebackup.sh
#!bash
###设置基础环境变量###
PATH=$PATH:/usr/pgsql-16/bin:
###设置需要备份DB的标识###
SID=ZSARMP
###设置PGDATA环境变量###
pgdata=/pgdata/ZSARMP
###设置pgbasebackup的用户###
PG_USER=postgres
###设置端口号###
PG_PORT=`cat $pgdata/postmaster.pid|sed -n 4p`
###设置日期便利用于判断备份路径###
DA=$(date +%-j)
###设置脚本日志存放路径###
scriptfolder=/pgdata/wistron/script/$SID
###设置DB归档的位置###
ARCHIVE=/pg_arch/"$SID"_arch
if (($DA%2==0));
then Singleordouble=double
else Singleordouble=single
fi
Location=/pgbackup/"$SID"_"$Singleordouble"
###备份前清空备份路径###
rm -rf $Location
###确认pgbasebackup开始备份时间###
echo "###### $SID PGbasebackup begin at `date` ######" > $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log
###执行pgbasebackup备份(-FT:指定备份格式为tar包 -Pv:输出详细的备份过程 -z:指定压缩格式 -Z5:指定压缩等级)###
pg_basebackup -Ft -Pv -Xs -z -Z5 -U $PG_USER -p $PG_PORT -D $Location -n -c fast &>> $scriptfolder/ pgbasebackup_"$SID"_"$Singleordouble".log
###备份归档的位置###
mkdir -p "$Location/archive"
###确认pgbasebackup结束备份时间###
echo "###### $SID PGbasebackup end at `date` ######" >> $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log
###判断备份是否成功###
logstatus=`grep "pg_basebackup: base backup completed" $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log`
percentcount=`grep "100%" $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log |wc -l`
logerror=`grep "not removed at user's request" $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log |wc -l`
###将昨天的备份日志及备份完成后当天的日志文件进行备份###
/bin/echo "###### $SID ARCH backup begin at `date` ######" >> $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log
/bin/find $ARCHIVE/* -name "*" -daystart -mtime 1 -exec cp -a {} $Location/archive \;
/bin/find $ARCHIVE/* -name "*" -daystart -mtime 1 >> $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log
/bin/find $ARCHIVE/* -name "*" -daystart -mtime 0 -exec cp -a {} $Location/archive \;
/bin/find $ARCHIVE/* -name "*" -daystart -mtime 0 >> $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log
/bin/echo "###### $SID ARCH backup end at `date` ######" >> $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log
if [ "$logstatus" = "pg_basebackup: base backup completed" ]
then
backupstatus="Successful"
else
if [ "$logerror" -gt 0 ] && [ "$percentcount" -gt 0 ]
then
backupstatus="Successful with error"
else
backupstatus="error"
fi
fi
echo "$SID PGbasebackup $backupstatus at `date`" >> $scriptfolder/pgbasebackup.log
cp $scriptfolder/pgbasebackup_"$SID"_"$Singleordouble".log /pgbackup/LOG/pgbasebackup_"$SID"_"$Singleordouble".log
###完成备份后发邮件通知###
mail -s "$SID PG PGbasebackup $backupstatus" -r "SE_PG_Basebackup_Check" "mzl320.wzs.wistron@wistron.com" < $scriptfolder/ pgbasebackup_"$SID"_"$Singleordouble".log
crontab -l
############Postgres DB basebackup###############
00 1 * * * sh /pgdata/wistron/script/ZSARMP/pgbasebackup.sh
if you want to recover the Database, you can refer to recovery DB SOP
- 2.3 Modify daily backup script(WIH)
vim /home/postgres/backup.sh
#!/bin/bash
# 2022.01.26
DAY="$(date +'%Y%m%d')"
TIME="$(date +'%Y%m%d%H%M%S')"
BACKPATH=/dbdump/POSTGRESQL/HQRPAD1/$DAY/$TIME
COPYPATH=/dbdump/POSTGRESQL/HQRPAD1
TARGET=/dbdump/POSTGRESQL/HQRPAD1
PATH=$PATH:/usr/pgsql-16/bin:
export PATH
#PG Information
PG_HOST=127.0.0.1
PG_USER=postgres
PG_PORT=5435
pg_basebackup -Ft -Pv -Xs -z -Z5 -U $PG_USER -h $PG_HOST -p $PG_PORT -D $BACKPATH
crontab -l
### Postgres DB backup, Dennis, 20220106###
0 22 * * * sh /pgdata/HQRPAD1/backup.sh > /tmp/log 2>&1
if you want to recover the Database, you can refer to recovery DB SOP
3. Backup PostgreSQL DB(postgres)¶
- 3.1 Before doing the recovery, we need a full backup via pg_basebackup
16384.tar.gz → archive for table space base.tar.gz → archive for database pg_wal.tar.gz → archive for wal file
-
3.2 Insert 300 data in test1 table. Every few minutes to insert data 3 times
- 3.2.1 First time
- 3.2.2 Second time
- 3.2.3 Third time
-
3.3 Now, we want to recovery the data after 2nd insert before 3rd insert.
- 3.3.1 shutdown DB first.
- 3.3.2 delete the database folder and empty HQRPAD1_tbs folder
- 3.3.3 go the backup tar folder, in this case is /tmp/DEV
-
3.3.4 create the database folder and un-tar base.tar.gz to the right path
-
3.3.4.1 unzip/tar the base.tar.gz
mkdir /pgdata/HQRPAD1 chmod 700 /pgdata/HQRPAD1 tar zxf base.tar.gz -C /pgdata/HQRPAD1 ll /pgdata/HQRPAD116384.tar.gz → archive for table space base.tar.gz → archive for database pg_wal.tar.gz → archive for wal file
-
3.3.4.2 unzip/tar pg_wal.tar.gz
-
3.3.4.3 unzip/tar 16384.tar.gz (tablespace)
-
3.3.5 we need to create symbolic in pg_tblspc under database folder
-
3.3.5.1 know which file name to be symboliced
-
3.3.5.2 know which file name to be symboliced
16384 will be the symbolic file name
-
3.3.6 revise recovery portion in postgresql.conf, and identify the time you want to recover. (this case, we want to recovery the data after 2nd insert before 3rd insert)
(The completed inserting time for 2nd inserting) - 3.3.7 we need to add one file named “recovery.signal” under database path. That means we tell postgres it will do the recovery from starting up DB
recovery.signal: tells PostgreSQL to enter normal archive recovery standby.signal: tells PostgreSQL to enter standby mode
- 3.3.8 now, we start the DB to see if the data recover to the time of 2nd inserting time
Check the DB record. It’s 600 records after 2nd inserting. At this moment, DB is read-only. Can’t insert any data

Try to insert but DB says it’s read-only mode

And database path 2 files will be renamed with .old. otherwise, recovery.signal still exists(database is recovery done, but read-only mode)
- 3.3.9 Finally, make sure the data is what we need to recovery. Then, we should to tell DB to continue(Read-Write mode) the transaction. Login as ‘postgres’, and execute below sql
At the same time, the recovery.signal file is gone under database path. That means the recovery is finished. DB backs to normal (read-write mode)


























