背景

冷备份, 以及逻辑备份都是某一个时间点的备份, 没有增量的概念.

如果数据库在运行过程中发生故障, 使用逻辑备份只能将数据库还原到备份时刻, 无法恢复到故障发生前的那个时刻.

又或者在使用过程中由于误操作修改或删除了重要数据, 需要还原到误操作前的那个时刻怎么办呢?

使用冷备份加上有效的归档文件可以实现任意时间点的恢复. 但是冷备份需要停库操作, 所以实用性不大.

本文要介绍的是在线的数据库文件备份, 弥补了冷备份的缺陷, 同时又支持基于时间点的恢复.

同时本文会介绍基于时间点(xid, target, time)的恢复方法.

准备工作

要实现增量的备份,我们需要配置一些参数。

postgresql.conf参数配置 :

1. wal日志级别 :

wal_level=archive 或 hot_standby  或 更高级别如果要使用pg_basebackup通过流复制协议远程备份,建议使用hot_standby及以上级别的wal。  

查看当前数据库的wal level :

pg93@db-172-16-3-33-> pg_controldata |grep wal_level
Current wal_level setting:            hot_standby  

如果结果不为hot_standby或者archive, 那么需要调整一下postgresql.conf. 并重启数据库.

2. 归档模式 :

    archive_mode = on  
如果原来是off的, 调整成on, 那么需要重启数据库.

3. 归档命令 :

首先要创建用于存放wal归档文件目录, 数据库启动用户需要写权限.

[root@db-172-16-3-33 postgresql-9.3beta1]# mkdir -p /pgdata/digoal/1921/data04/pg93archdir
[root@db-172-16-3-33 postgresql-9.3beta1]# chown pg93:pg93 /pgdata/digoal/1921/data04/pg93archdir
[root@db-172-16-3-33 postgresql-9.3beta1]# chmod 700 /pgdata/digoal/1921/data04/pg93archdir  

然后在$PGDATA中创建归档脚本

[root@db-172-16-3-33 postgresql-9.3beta1]# su - pg93
pg93@db-172-16-3-33-> cd $PGDATA  pg93@db-172-16-3-33-> vi archive.sh
#!/bin/bash  export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.3
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d"`
export PATH=$PGHOME/bin:$PATH:.  BASEDIR="/pgdata/digoal/1921/data04/pg93archdir"  if [ ! -d $BASEDIR/$DATE ]; then  mkdir -p $BASEDIR/$DATE  if [ ! -d $BASEDIR/$DATE ]; then  echo "error mkdir -p $BASEDIR/$DATE"  exit 1  fi
fi  cp $1 $BASEDIR/$DATE/$2
if [ $? -eq 0 ]; then  exit 0
else  echo -e "cp $1 $BASEDIR/$DATE/$2 error"  exit 1
fi  echo -e "backup failed"
exit 1  

给archive.sh添加可执行权限 :

chmod 700 archive.sh  

配置postgresql.conf中的归档命令 :

archive_command = 'archive.sh %p %f'  

修改完后reload配置文件即可

pg_ctl reload  

配置完后检查一下归档是否正常 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_switch_xlog();  pg_switch_xlog
----------------  F/2095D8
(1 row)
digoal=# select pg_switch_xlog();  pg_switch_xlog
----------------  F/1000000
(1 row)
digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_switch_xlog();  pg_switch_xlog
----------------  F/10000E8
(1 row)
digoal=# checkpoint;
^[[ACHECKPOINT
digoal=# select pg_switch_xlog();  pg_switch_xlog
----------------  F/20000E8
(1 row)  

查看归档文件 :

pg93@db-172-16-3-33-> cd /pgdata/digoal/1921/data04/pg93archdir
pg93@db-172-16-3-33-> ll
total 4.0K
drwx------ 2 pg93 pg93 4.0K May 27 10:56 20130527
pg93@db-172-16-3-33-> cd 20130527/
pg93@db-172-16-3-33-> ll
total 48M
-rw------- 1 pg93 pg93 16M May 27 10:56 000000030000000F00000000
-rw------- 1 pg93 pg93 16M May 27 10:56 000000030000000F00000001
-rw------- 1 pg93 pg93 16M May 27 10:56 000000030000000F00000002  

4. 建议设置work process,sender进程数,才可以通过pg_basebackup使用流复制协议进行备份。

必须大于0,每个流复制连接需要一个wal sender进程。

max_worker_processes = 16
max_wal_senders = 8

5. 建议设置wal_keep_segments,确保非常大的数据库,在漫长的备份时间周期内xlog不被覆盖。

注意配置之后,pg_xlog至少会占用wal_keep_segments * wal文件大小 的空间。

需要预留好空间

wal_keep_segments = 1024

备份

具备了这些前提条件之后, 就可以进行在线备份了.

在线备份可以使用拷贝, rsync, 或者pg_basebackup命令进行.

方法一, 拷贝

首先在数据库中以超级用户执行如下命令 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# select pg_start_backup(now()::text);  pg_start_backup
-----------------  F/3000028
(1 row)  

这个命令执行的目的是在$PGDATA中记录一个标签文件, 包含标签名now()::text, 以及执行这条指令的启动时间和WAL位置.

标签文件信息如下 :

[root@db-172-16-3-33 postgresql-9.3beta1]# su - pg93
pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> cat backup_label
START WAL LOCATION: F/3000028 (file 000000030000000F00000003)
CHECKPOINT LOCATION: F/3000060
BACKUP METHOD: pg_start_backup
BACKUP FROM: master
START TIME: 2013-05-27 11:02:58 CST
LABEL: 2013-05-27 11:02:58.578713+08  

接下来就可以拷贝数据文件了.

pg93@db-172-16-3-33-> cp -r -L $PGDATA /pgdata/digoal/1921/data04/pg93backup/20130527_onlinebackup  

拷贝完后清除备份文件中pg_xlog和pg_log中的内容, 因为这些是不需要的.

cd /pgdata/digoal/1921/data04/pg93backup/20130527_onlinebackup/pg_xlog
rm -rf *
cd /pgdata/digoal/1921/data04/pg93backup/20130527_onlinebackup/pg_log
rm -rf *  

接下来使用超级用户在数据库中执行如下命令 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# select pg_stop_backup();
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived  pg_stop_backup
----------------  F/3001A20
(1 row)  

然后要备份这段时间产生的归档文件 :

需要的归档文件是哪些呢?

备份开始是的XLOG文件在backup_label中已经指出了000000030000000F00000003, 结束时的XLOG文件也可以从pg_stop_backup()的输出中得到 :

digoal=#  select pg_xlogfile_name('F/3001A20');  pg_xlogfile_name
--------------------------  000000030000000F00000003
(1 row)  

如果你的PostgreSQL版本没有这个函数, 那么就自己计算一下文件名 :

参考 :

http://blog.163.com/digoal@126/blog/static/1638770402012914112949546/

因此本例中需要的文件只有1个就是000000030000000F00000003

如果归档文件本来就不是放在本地文件系统中, 那么也不需要二次备份归档文件. 只要别删掉需要的归档文件就行了.

方法二, rsync

方法与拷贝类似, 也需要先执行pg_start_backup, 然后调用rsync, 最后调用pg_stop_backup.

命令举例 :

pg93@db-172-16-3-33-> rsync -acvz -L --exclude "pg_xlog" --exclude "pg_log" $PGDATA /pgdata/digoal/1921/data04/pg93backup/20130527_backup  

方法三, pg_basebackup

pg_basebackup是PostgreSQL 9.1 引入的一个数据库备份命令, pg_basebackup利用流复制协议传输数据库文件.

使用pg_basebackup备份数据库需要用到超级用户或者replication角色用户.

另外就是pg_basebackup不需要执行pg_start_backup和pg_stop_backup, 因为命令中已经封装了这些操作.

并且支持多个pg_basebackup并行备份同一个数据库集群.

例如 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# create role replica login replication encrypted password 'replica';
CREATE ROLE  

配置pg_hba.conf , 允许连接.

host    replication     replica        172.16.3.40/32            md5
pg_ctl reload  

在另一台主机备份 :

pg93@db-172-16-3-40-> pg_basebackup -D ./basebackup_20130527 -F p -X stream -h 172.16.3.33 -p 1999 -U replica
Password:
WARNING:  skipping special file "./.s.PGSQL.1999"  

需要注意, 以pg_basebackup备份, 如果表空间使用了软链接, 那么备份时在目标端也会创建软链接, 因此需要先保证目录存在并有写权限.

例如本例 :

pg93@db-172-16-3-40-> cd basebackup_20130527/
pg93@db-172-16-3-40-> cd pg_tblspc/
pg93@db-172-16-3-40-> ll
total 0
lrwxrwxrwx 1 pg93 pg93 47 May 27 12:28 26425 -> /pgdata/digoal/1921/data03/pg93/1999/tbs_digoal  

那么目标端的/pgdata/digoal/1921/data03/pg93/1999 这个目录要先创建好, 并提供写权限.

PITR还原举例

PostgreSQL 支持指定还原点的位置, 即数据库恢复到什么位置停下来.

4个recovery.conf参数控制恢复停止在哪个位置.

1. recovery_target_name, 指pg_create_restore_point(text)创建的还原点, 如果有重名的还原点, 那么在recovery过程中第一个遇到的还原点即停止.

2. recovery_target_time, 指XLOG中记录的recordXtime(xl_xact_commit_compact->xact_time), 配合recovery_target_inclusive使用,

如果在同一个时间点有多个事务回滚或提交, 那么recovery_target_inclusive=false则恢复到这个时间点第一个回滚或提交的事务(含), recovery_target_inclusive=true则恢复到这个时间点最后一个回滚或提交的事务(含).   如果时间点上刚好只有1个事务回滚或提交, 那么recovery_target_inclusive=true和false一样, 恢复将处理到这个事务包含的xlog信息(含).   如果时间点没有匹配的事务提交或回滚信息, 那么recovery_target_inclusive=true和false一样, 恢复将处理到这个时间后的下一个事务回滚或提交的xlog信息(含).

3. recovery_target_xid, 指XLogRecord->xl_xid, 可以配合recovery_target_inclusive使用, 但是recovery_target_inclusive只影响日志的输出, 并不影响恢复进程截至点的选择, 截至都截止于这个xid的xlog位置. 也就是说无论如何都包含了这个事务的xlog信息的recovery.

这里需要特别注意xid的信息体现在结束时, 而不是分配xid时. 所以恢复到xid=100提交|回滚点, 可能xid=102已经先提交了. 那么包含xid=102的xlog信息会被recovery.

4. recovery_target_inclusive

还原点的详细介绍可参考 :

http://blog.163.com/digoal@126/blog/static/163877040201303082942271/

在还原前, 对数据库做一些DML操作, 配合这些DML操作来讲解一下这几个参数的含义.

场景1

1.
begin1;query1;commit1; begin2; query2_1; pg_create_restore_point(text); query2_2; commit2;

按照以上描述, 使用recovery_target_name恢复数据库恢复后应该包含query1的变更, 但是不包含query2_1和query2_2的变更.

begin1;query1;commit1; -- SESSION A :
digoal=# create table pitr_test(id int, info text);
CREATE TABLE
digoal=# insert into pitr_test values (1,'test');
INSERT 0 1
begin2; query2_1; -- SESSION A :
digoal=# begin;
BEGIN
digoal=# insert into pitr_test values (2,'test');
INSERT 0 1  pg_create_restore_point(text); -- SESSION B :
digoal=# select pg_create_restore_point('pitr_test');  pg_create_restore_point
-------------------------  F/B01F8C8
(1 row)  query2_2; commit2; -- SESSION B :
digoal=# insert into pitr_test values (3,'test');
INSERT 0 1
digoal=# commit;
COMMIT  

切换日志, 归档 :

digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_xlogfile_name(pg_switch_xlog());  pg_xlogfile_name
--------------------------  000000030000000F0000000C
(1 row)
digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_xlogfile_name(pg_switch_xlog());  pg_xlogfile_name
--------------------------  000000030000000F0000000D
(1 row)  

使用拷贝的备份以及归档日志还原 :

关闭数据库

pg93@db-172-16-3-33-> pg_ctl stop -m fast
waiting for server to shut down.... done
server stopped  

删除数据库目录以及表空间目录

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> cd pg_tblspc/
pg93@db-172-16-3-33-> ll
total 0
lrwxrwxrwx 1 pg93 pg93 47 May 26 18:04 26425 -> /pgdata/digoal/1921/data03/pg93/1999/tbs_digoal
pg93@db-172-16-3-33-> rm -rf /pgdata/digoal/1921/data03/pg93/1999/tbs_digoal/*
pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> rm -rf *  

还原备份以及表空间软链接

pg93@db-172-16-3-33-> cp -r /pgdata/digoal/1921/data04/pg93backup/20130527_onlinebackup/* $PGDATA/
pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> cd pg_tblspc/
pg93@db-172-16-3-33-> ll
total 4.0K
drwx------ 3 pg93 pg93 4.0K May 27 14:32 26425
pg93@db-172-16-3-33-> mv 26425/* /pgdata/digoal/1921/data03/pg93/1999/tbs_digoal/
pg93@db-172-16-3-33-> rm -rf 26425
pg93@db-172-16-3-33-> ln -s /pgdata/digoal/1921/data03/pg93/1999/tbs_digoal ./26425
pg93@db-172-16-3-33-> ll
total 0
lrwxrwxrwx 1 pg93 pg93 47 May 27 14:34 26425 -> /pgdata/digoal/1921/data03/pg93/1999/tbs_digoal  

创建pg_log目录, 存放日志 :

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> mkdir -p pg_log  

配置$PGDATA/recovery.conf

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> cp $PGHOME/share/recovery.conf.sample ./recovery.conf
vi recovery.conf
restore_command = 'recovery.sh /pgdata/digoal/1921/data04/pg93archdir %f %p'            # e.g. 'cp /mnt/server/archivedir/%f %p'
recovery_target_name = 'pitr_test'      # e.g. 'daily backup 2011-01-26'
recovery_target_timeline = 'latest'  

创建恢复脚本 :

pg93@db-172-16-3-33-> cat recovery.sh
#!/bin/bash  export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.3
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d"`
export PATH=$PGHOME/bin:$PATH:.  BASEDIR=$1  find $BASEDIR -name $2 -exec cp {} $3 \;  

添加可执行权限 :

pg93@db-172-16-3-33-> chmod 700 recovery.sh  

启动数据库

pg93@db-172-16-3-33-> pg_ctl start
server starting
pg93@db-172-16-3-33-> LOG:  00000: loaded library "pg_stat_statements"
LOCATION:  load_libraries, miscinit.c:1296  

查看还原点是否与预计匹配 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# select ctid,* from pitr_test ;  ctid  | id | info
-------+----+------  (0,1) |  1 | test
(1 row)
digoal=# insert into pitr_test values(2,'new');
INSERT 0 1
digoal=# select ctid,* from pitr_test ;  ctid  | id | info
-------+----+------  (0,1) |  1 | test  (0,3) |  2 | new
(2 rows)  

新插入的数据ctid=3, 说明query2_1的xlog信息被恢复了, 但是回滚了. 如果没有执行info=new的ctid应该=2.

场景2

2.
commit_xact1; time1; rollback_xact2; time2; commit_xact3; commit_xact4;

按照以上描述, 使用recovery_target_time恢复,

如果recovery_target_time=time1, 不管recovery_target_inclusive=true|false, 恢复后应该都只能看到commit_xact1;的数据变更. 因为rollback_xact2回滚了, 不过使用ctid也能看出回滚的影响, 因为rollback_xact2;的xlog是需要处理的.  如果recovery_target_time=time2, 不管recovery_target_inclusive=true|false, 恢复后应该都只能看到commit_xact3;的数据变更. 但是绝对看不到commit_xact4的变更, 即使ctid也不会有影响, 因为commit_xact4;的xlog不会被处理.  
commit_xact1; -- SESSION A :
digoal=# truncate pitr_test ;
TRUNCATE TABLE
digoal=# insert into pitr_test values (1,'test');
INSERT 0 1  time1; -- SESSION A :
digoal=# select now();  now
-------------------------------  2013-05-27 15:39:57.033134+08
(1 row)  rollback_xact2; -- SESSION A :
digoal=# begin;
BEGIN
digoal=# insert into pitr_test values (2,'rollback');
INSERT 0 1
digoal=# insert into pitr_test values (3,'rollback');
INSERT 0 1
digoal=# rollback;
ROLLBACK  time2; -- SESSION A :
digoal=# select now();  now
-------------------------------  2013-05-27 15:40:24.055161+08
(1 row)  commit_xact3; -- SESSION A :
digoal=# insert into pitr_test values (4,'new');
INSERT 0 1  commit_xact4; -- SESSION A :
digoal=# insert into pitr_test values (5,'new');
INSERT 0 1  

切换日志, 归档 :

digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_xlogfile_name(pg_switch_xlog());  pg_xlogfile_name
--------------------------  000000010000000000000003
(1 row)
digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_xlogfile_name(pg_switch_xlog());  pg_xlogfile_name
--------------------------  000000010000000000000004
(1 row)  

使用拷贝的备份以及归档日志还原 :

关闭数据库

pg93@db-172-16-3-33-> pg_ctl stop -m fast
waiting for server to shut down.... done
server stopped  

删除数据库目录以及表空间目录(为简化例子, 本例无新建的表空间.)

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> rm -rf *  

还原备份以及表空间软链接

pg93@db-172-16-3-33-> cp -r /pgdata/digoal/1921/data04/pg93backup/20130527_onlinebackup/* $PGDATA  

创建pg_log目录, 存放日志 :

pg93@db-172-16-3-33-> cd $PGDATA  

配置$PGDATA/recovery.conf

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> cp $PGHOME/share/recovery.conf.sample ./recovery.conf  vi recovery.conf
restore_command = 'recovery.sh /pgdata/digoal/1921/data04/pg93archdir %f %p'            # e.g. 'cp /mnt/server/archivedir/%f %p'
recovery_target_time = '2013-05-27 15:39:57.033134+08'
recovery_target_inclusive = false
recovery_target_timeline = 'latest'  

创建恢复脚本 :

pg93@db-172-16-3-33-> cat recovery.sh
#!/bin/bash  export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.3
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d"`
export PATH=$PGHOME/bin:$PATH:.  BASEDIR=$1  find $BASEDIR -name $2 -exec cp {} $3 \;  

添加可执行权限 :

pg93@db-172-16-3-33-> chmod 700 recovery.sh  

启动数据库

pg93@db-172-16-3-33-> pg_ctl start
server starting
pg93@db-172-16-3-33-> LOG:  00000: loaded library "pg_stat_statements"
LOCATION:  load_libraries, miscinit.c:1296  

查看还原点是否与预计匹配 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# select ctid,* from pitr_test ;  ctid  | id | info
-------+----+------  (0,1) |  1 | test
(1 row)
digoal=# insert into pitr_test values(10,'new');
INSERT 0 1
digoal=# select ctid,* from pitr_test ;  ctid  | id | info
-------+----+------  (0,1) |  1 | test  (0,4) | 10 | new
(2 rows)  

新插入的数据ctid=4, 说明rollback_xact2;的xlog信息被恢复了, 但是回滚了. 如果没有执行info=new的ctid应该=2.

其他几种搭配就不测试了, 原理已经介绍清楚了. 有兴趣的朋友可以自行测试.

场景3

3.
commit_xact1;begin2;query2_1;commit_xact3;commit_xact4;query2_2;rollback2;commit_xact5;

recovery_target_xid=commit_xact1, 无论recovery_target_inclusive=true|false, 恢复后数据库将包含commit_xact1的数据变更;

recovery_target_xid=rollback2; 则包含xact1,xact3,xact4的变更以及xact2的回滚;

recovery_target_xid=xact5; 则包含所有xlog信息.

commit_xact1; -- SESSION A :
digoal=# truncate pitr_test ;
TRUNCATE TABLE
digoal=# begin;
BEGIN
digoal=# select txid_current();  txid_current
--------------  1691
(1 row)
digoal=# insert into pitr_test values (1,'test');
INSERT 0 1
digoal=# end;
COMMIT  begin2;query2_1; -- SESSION A :
digoal=# begin;
BEGIN
digoal=# select txid_current();  txid_current
--------------  1692
(1 row)
digoal=# insert into pitr_test values (1692,'test');
INSERT 0 1  commit_xact3;commit_xact4; -- SESSION B :
digoal=# begin;
BEGIN
digoal=# select txid_current();  txid_current
--------------  1693
(1 row)
digoal=# insert into pitr_test values (1693,'teset');
INSERT 0 1
digoal=# end;
COMMIT
digoal=# begin;
BEGIN
digoal=# select txid_current();  txid_current
--------------  1694
(1 row)
digoal=# insert into pitr_test values (1693,'teset');
INSERT 0 1
digoal=# insert into pitr_test values (1694,'teset');
INSERT 0 1
digoal=# end;
COMMIT  query2_2;rollback2; -- SESSION A :
digoal=# insert into pitr_test values (1692,'new_test');
INSERT 0 1
digoal=# rollback;
ROLLBACK  commit_xact5; -- SESSION A :
digoal=# begin;
BEGIN
digoal=# select txid_current();  txid_current
--------------  1695
(1 row)
digoal=# insert into pitr_test values (1695,'test');
INSERT 0 1
digoal=# commit;
COMMIT  

切换日志, 归档 :

digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_xlogfile_name(pg_switch_xlog());  pg_xlogfile_name
--------------------------  000000020000000000000003
(1 row)
digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_xlogfile_name(pg_switch_xlog());  pg_xlogfile_name
--------------------------  000000020000000000000004
(1 row)  

使用拷贝的备份以及归档日志还原 :

关闭数据库

pg93@db-172-16-3-33-> pg_ctl stop -m fast
waiting for server to shut down.... done
server stopped  

删除数据库目录以及表空间目录(为简化例子, 本例无新建的表空间.)

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> rm -rf *  

还原备份以及表空间软链接

pg93@db-172-16-3-33-> cp -r /pgdata/digoal/1921/data04/pg93backup/20130527_onlinebackup/* $PGDATA  

创建pg_log目录, 存放日志 :

pg93@db-172-16-3-33-> cd $PGDATA  

配置$PGDATA/recovery.conf

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> cp $PGHOME/share/recovery.conf.sample ./recovery.conf
vi recovery.conf
restore_command = 'recovery.sh /pgdata/digoal/1921/data04/pg93archdir %f %p'            # e.g. 'cp /mnt/server/archivedir/%f %p'
recovery_target_xid = '1692'
recovery_target_inclusive = false
recovery_target_timeline = 'latest'  

创建恢复脚本 :

pg93@db-172-16-3-33-> cat recovery.sh
#!/bin/bash  export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.3
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d"`
export PATH=$PGHOME/bin:$PATH:.  BASEDIR=$1  find $BASEDIR -name $2 -exec cp {} $3 \;  

添加可执行权限 :

pg93@db-172-16-3-33-> chmod 700 recovery.sh  

启动数据库

pg93@db-172-16-3-33-> pg_ctl start
server starting
pg93@db-172-16-3-33-> LOG:  00000: loaded library "pg_stat_statements"
LOCATION:  load_libraries, miscinit.c:1296  

查看还原点是否与预计匹配 :

pg93@db-172-16-3-33-> psql
psql (9.3devel)
Type "help" for help.
digoal=# select ctid,* from pitr_test ;  ctid  |  id  | info
-------+------+-------  (0,1) |    1 | test  (0,3) | 1693 | teset  (0,4) | 1693 | teset  (0,5) | 1694 | teset
(4 rows)
digoal=# insert into pitr_test values(10,'new');
INSERT 0 1
digoal=# select ctid,* from pitr_test ;  ctid  |  id  | info
-------+------+-------  (0,1) |    1 | test  (0,3) | 1693 | teset  (0,4) | 1693 | teset  (0,5) | 1694 | teset  (0,7) |   10 | new
(5 rows)  

因为只有当record_info等于XLOG_XACT_ABORT,XLOG_XACT_COMMIT或者XLOG_XACT_COMMIT_COMPACT, 或者自建还原点时才可以被作为截至点,

所以本例使用xid=1692作为截至点, xlog会应用到query2_2;rollback2; -- SESSION A : 这个位置(并且包含这个xlog信息).

因此在此之前应该插入了6条记录, 所以新插入的数据ctid=7, 再次说明query2_2;rollback2;的xlog信息被恢复了, 但是回滚了.

其他几种搭配就不测试了, 原理已经介绍清楚了. 有兴趣的朋友可以自行测试.

自动备份

这个可以结合操作系统的定时脚本来实现, 在Linux中可以使用crontab.

例如 :

1. 首先规划好存放数据库数据文件的目录.

mkdir -p /pgdata/digoal/1921/data04/pg93backup
chown -R pg93:pg93 /pgdata/digoal/1921/data04/pg93backup
chmod 700 /pgdata/digoal/1921/data04/pg93backup  

2. 编写备份脚本

pg93@db-172-16-3-33-> cd $PGDATA
pg93@db-172-16-3-33-> vi backup.sh
#!/bin/bash  export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.3
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d"`
export PATH=$PGHOME/bin:$PATH:.
export PGDATA=/pgdata1999  BASEDIR="/pgdata/digoal/1921/data04/pg93backup"  date +%F%T  if [ ! -d $BASEDIR/$DATE ]; then  mkdir -p $BASEDIR/$DATE  if [ $? -eq 0 ]; then  psql -h 127.0.0.1 -p 1999 -U postgres postgres -c "select pg_start_backup(now()::text)"  if [ $? -eq 0 ]; then  cp -r -L $PGDATA $BASEDIR/$DATE  else  echo -e "select pg_start_backup(now()::text) error"  exit 1  fi  psql -h 127.0.0.1 -p 1999 -U postgres postgres -c "select pg_stop_backup()"  date +%F%T  echo -e "backup successed"  exit 0  else  echo -e "mkdir -p $BASEDIR/$DATE error"  exit 1  fi
else  echo -e "$DATE backuped, don't backup repeated"  exit 1
fi  

修改权限

pg93@db-172-16-3-33-> chmod 700 backup.sh  

3. 测试

pg93@db-172-16-3-33-> ./backup.sh   pg_start_backup
-----------------  0/6000028
(1 row)  NOTICE:  pg_stop_backup complete, all required WAL segments have been archived  pg_stop_backup
----------------  0/60000F0
(1 row)  

pg93@db-172-16-3-33-> 再次执行则退出, 因为今天已经备份了.

pg93@db-172-16-3-33-> ./backup.sh
20130527 backuped, don't backup repeated  

4. 配置crontab
首先删除当天备份

rm -rf /pgdata/digoal/1921/data04/pg93backup/20130527  

配置自动备份

su - pg93
crontab -e
40 16 * * * /pgdata1999/backup.sh >>/tmp/backup.log 2>&1  

5. 检查是否自动备份.

pg93@db-172-16-3-33-> cat /tmp/backup.log
2013-05-2716:40:01  pg_start_backup
-----------------  0/8000028
(1 row)  NOTICE:  pg_stop_backup complete, all required WAL segments have been archived  pg_stop_backup
----------------  0/80000F0
(1 row)  2013-05-2716:40:02
backup successed  

检查备份成功后把crontab调整为你需要的备份时间即可. 例如每天都凌晨2点开始备份.

0 2 * * * /pgdata1999/backup.sh >>/tmp/backup.log 2>&1  

参考

1. http://blog.163.com/digoal@126/blog/static/1638770402012914112949546/
2. http://blog.163.com/digoal@126/blog/static/163877040201303082942271/

PostgreSQL 最佳实践 - 在线增量备份与任意时间点恢复相关推荐

  1. (新零售)商户网格化运营 - 阿里云RDS PostgreSQL最佳实践

    原文地址 背景 伟大的马老师说: "纯电商时代很快会结束,未来的十年.二十年,没有电子商务这一说,只有新零售这一说,也就是说线上线下和物流必须结合在一起,才能诞生真正的新零售" 线 ...

  2. 时间、空间、对象 海量极速多维检索 - 阿里云RDS PostgreSQL最佳实践

    标签 PostgreSQL , 时间 , 空间 , 对象属性 , 多维度检索 , 海量 , 空间索引 , 数据分区 , 块级索引BRIN , 多级索引 , GIN倒排索引 , JSON索引 , 多列索 ...

  3. db2设置数据库增量备份_DB2在线增量备份 还原增量备份及前滚恢复

    1.更改数据库参数 logretain, userexit, trackmod 为 on 2.更改参数之后完全离线备份数据库一次 3.之后就可以进行在线.在线增量备份了 测试结果通过,脚本如下. 重要 ...

  4. MSSQL · 最佳实践 · SQL Server备份策略

    摘要 在上一期月报中我们分享了SQL Server三种常见的备份技术及工作方式,本期月报将分享如何充分利用三者的优点来制定SQL Server数据库的备份和还原策略以达到数据库快速灾难恢复能力. 上期 ...

  5. mysql整备_【mysql】使用xtrabackup在线增量备份及恢复数据库

    一.Percona Xtrabackup 简介 1.Xtrabackup  bin目录文件 介绍 1)innobackupex innobackupex 是xtrabackup的一个符号链接 . in ...

  6. SAP BPC最佳实践-BPC系统备份及恢复

    BPC系统作为基于BW的产品,但是由于在维度.属性等若干概念上与BW的差别,在传输.复制.备份恢复方面都难以沿用BW的传统策略.举一个例子,如果我们需要在生产系统中恢复某一个时间点的BPC Cube中 ...

  7. postgres9.5.7 wal日志归档和任意时间点恢复数据

    wal日志备份 目录规划 /mnt2/postgresql_basebak/data #基础备份目录 /mnt2/postgresql_recover/data #还原目录 /mnt2/postgre ...

  8. 行存、列存,堆表、AO表性能对比 - 阿里云HDB for PostgreSQL最佳实践

    标签 PostgreSQL , GIS , PostGIS , Greenplum , 空间检索 , GiST , B-Tree , geohash 背景 <Greenplum 行存.列存,堆表 ...

  9. 代码干货 | 行存、列存_堆表、AO表性能对比-阿里云HDB for PostgreSQL最佳实践

    本文来源于阿里云-云栖社区,原文点击这里. 标签 PostgreSQL , GIS , PostGIS , Greenplum , 空间检索 , GiST , B-Tree , geohash 背景 ...

最新文章

  1. linux配置oracle11G监听及本地网络服务 及 数据库建库
  2. rocketmq还要eventbus_ListEventBuses_ListEventBuses_事件总线_C# SDK_阿里云SDK参考_事件总线EventBridge - 阿里云...
  3. 使用IDEA2017创建java web +maven项目
  4. 网络基础知识-TCP/IP协议各层详解
  5. 学习笔记大型《构建高性能web站点》
  6. 为避免攻击,研究员把严重的比特币漏洞详情焐了两年
  7. python Pandas文件读写
  8. 编程零基础,如何学 Python ?
  9. 零基础 VS2012 串口编程
  10. “天外来客”讲述太阳系“童年”故事
  11. 新玺配资:板块轮动加快 多看少动均衡配置为主
  12. HITB CTF 2018 gundam 做题笔记
  13. SQL语法INSERT INTO_大数据培训
  14. centos如何安装软件
  15. 安装YApi 接口管理平台
  16. chrome浏览器模拟慢网速环境
  17. Hive自定义函数(字母大小写转换)
  18. 使用JDBC连接mysql遇到的若干问题及解决办法
  19. 01背包python解法_0-1背包问题及Python代码实现
  20. 神经网络之梯度下降法及其实现

热门文章

  1. html 文字悬停翻转,html5+TweenMax.js鼠标悬停文字翻转动画特效
  2. db2 查看表结构_数据库结构文档的生成利器
  3. java arraylist add时默认调用tostring_java中如何调用toString命名的方法?
  4. 谈谈Web Workers
  5. mysql_real_connect阻塞_mysql_real_connect 参数注意-阿里云开发者社区
  6. java报错空指针异常_springboot全局异常捕获,真香
  7. html 空行_一篇文章学习html「经典案例」
  8. android alertdialog view,Android AlertDialog 方法setView(view,0,0,0,0)开发自定义对话框
  9. android meminfo,Android中dumpsys meminfo与/proc/meminfo获取空闲内存不一致的问题
  10. win7 OEM设置工具