postgresql连续归档及时间点恢复的操作
简介
前面我们介绍了通过pgsql的流复制在生产环境中搭建高可用环境来保证服务的可持续性;我们也要对数据库进行周期备份,来防止数据的丢失,这就需要连续归档,它不仅可以用于大型数据库的增量备份和恢复,也可以用于搭建standby镜像备份。
PostgreSQL默认处于非归档模式。开启归档模式,主要涉及到三个参数:wal_level,archive_mode和archive_commandwal_level参数默认为mininal,设置此参数为archive或者之上的级别都可以打开归档。当postgresql需要传输归档日志时,会调用archive_command指定的shell命令。
归档文件传输成功时,shell命令要返回0,此时,postgresql会认为归档文件已经传输成功,因此可以删除或者重新循环利用归档文件。当shell命令返回非0值时,postgresql会保留所有未成功传输的归档日志,并不断尝试重新传输,直到成功。如果归档命令一直不成功,pg_xlog目录会持续增长,有耗尽服务器存储空间的可能,此时postgresql会PANIC关闭,直到释放存储空间。
另外将归档WAL日志存储在本机上是风险极高,不被推荐的。postgresql通过archive_command提供了存储WAL日志的灵活性,可以将归档日志存储到挂装的NFS目录,磁带,刻录到光盘,也可以将WAL日志通过ssh/scp,rsync传输到异机保存。
**注意:**archive_command及restore_command命令将以运行PostgreSQL的系统用户的身份运行。Centos系统里,这个系统用户是postges。
环境说明
Role | IP | 系统 | 数据库 |
---|---|---|---|
源库 | 10.10.10.60 | Centos6.5 | postgresql9.2 |
备份库 | 10.10.10.61 | Centos6.5 | postgresql9.2 |
需求说明:源库产生归档日志,并传输到备份库上的归档目录/data/pg_archive;备份库利用归档日志,恢复至源库的任意时间点的数据。
注意:基础环境我们基于postgresql流复制,但是备份库作为一个独立的库,此时请保证recovery.conf中的standby_mode=off
环境配置
1.ssh无密码登录
由于我们备份和还原过程中所用的archive_command和restore_command命令都以postgres用户运行,因此我们需要针对postgres用户实现ssh无密码登录。
#源库 ssh-ketgen-trsa scpid_rsa.pubpostgres@10.10.10.60:/var/lib/pgsql/.ssh/authorized_keys #备份库 ssh-ketgen-trsa scpid_rsa.pubpostgres@10.10.10.61:/var/lib/pgsql/.ssh/authorized_keys
**注意:**yum安装postgresql时,默认生成的postgres用户的家目录在/var/lib/pgsql
2.配置备份库的归档目录
#备份库 mkdir-p/data/pg_archive chmodpostgres.postgres/data/pg_archive
说明:源库产生的归档日志,要存到到异地备份库的/data/pg_archive下。
3.修改源库的postgresql.conf
在postgresql.conf中添加以下几行
#开启归档模式 archive_mode=on archive_command='ssh10.10.10.60test!-f/data/pg_archive/%f&&scp%p10.10.10.60:/data/pg_archive/%f'
其中:%p表示wal日志文件的路径,%f表示wal日志文件名称。archive_command表示先验证备份库的归档目录下是否存在同名文件,以免发生覆盖丢失数据,若不存在将源库上产生的归档日志保存到备份库的/data/pg_archive目录下。
注意:
(a)archive_timeout强制N秒以后进行一次归档,若设置太小,很快就会超过wal_keep_segments=16,导致数据覆盖丢失,因此不要盲目设置。
(b)归档模式的开启,只有在wal_level=hot_standby或archive
4.重载源库并查看
pg_ctlreload-D/data/pgsql/data postgres=#showarchive_mode; archive_mode -------------- on (1row)
模拟归档备份
1.查看源库上的pg_xlog目录
-bash-4.2$llpg_xlog total16388 -rw-------.1postgrespostgres16777216Apr2113:42000000010000000000000001 drwx------.2postgrespostgres4096Apr2113:36archive_status
此时archive_status目录为存放归档日志的状态,若归档已经产生,但没有传输成功则为xxx.ready,并且一直会保留直至传输成功,然后状态变为xxx.done;此时目录为空
2.在源库上添加数据
此时由于数据库为空,我们来创建testdb库,并添加数据
postgres=#createdatabasetestdb; CREATEDATABASE postgres=#createtablet1(idint4,create_timetimestamp(0)withouttimezone); CREATETABLE postgres=#insertintot1values(1,now()); INSERT01 postgres=#insertintot1values(2,now()); INSERT01 postgres=#select*fromt1; id|create_time ----+--------------------- 1|2016-04-2113:49:34 2|2016-04-2113:49:48 (2rows)
3.在源库上手动切换归档
postgres=#selectpg_switch_xlog(); pg_switch_xlog ---------------- 0/1821010 (1row)
正常情况下,wal日志段在达到16M后会自动归档,由于测试我们使用手动切换归档。
4.查看源库pg_xlog目录
-bash-4.2$llpg_xlog/ total16388 -rw-------.1postgrespostgres16777216Apr2113:42000000010000000000000001 drwx------.2postgrespostgres4096Apr2113:36archive_status -bash-4.2$lspg_xlog/ 000000010000000000000001000000010000000000000002archive_status -bash-4.2$lspg_xlog/archive_status/ 000000010000000000000001.ready
此时归档日志的状态为ready,说明此日志没有传输成功,查看日志
vim/data/pgsql/pg_log/postgresql-Thu.log ssh:connecttohost10.10.10.60port22:Connectiontimedout^M FATAL:archivecommandfailedwithexitcode255 DETAIL:Thefailedarchivecommandwas:ssh10.10.10.68test!-f/data/pg_archive/000000010000000000000001&&scppg_xlog/00000001000000000000000110.10.10.60:/data/pg_archive/000000010000000000000001 LOG:archiverprocess(PID22284)exitedwithexitcode1
原来是由于ip地址错误导致无法通过ssh传输,更改ip为10.10.10.61后,再次产生归档才能再次重新传输。
注意:触发归档有三种方式:
1.手动切换wal日志,selectpg_switch_xlog()
2.wal日志写满后触发归档,配置文件默认达到16M后就会触发归档,wal_keep_segments=16
3.归档超时触发归档,archive_timeout
在此我们使用的是手挡切换归档。
postgres=#insertintot1values(3,now()); INSERT01 postgres=#insertintot1values(4,now()); INSERT01 postgres=#selectpg_switch_xlog(); pg_switch_xlog ---------------- 0/2000310 (1row) postgres=#selectpg_switch_xlog(); pg_switch_xlog ---------------- 0/3000000 (1row) postgres=#selectpg_switch_xlog(); pg_switch_xlog ---------------- 0/30000D8 (1row)
再次查看pg_xlog目录
-bash-4.2$llpg_xlog/archive_status/ total0 -rw-------.1postgrespostgres0Apr2113:51000000010000000000000001.done -rw-------.1postgrespostgres0Apr2114:00000000010000000000000002.done -rw-------.1postgrespostgres0Apr2114:04000000010000000000000003.done
5.查看备份库上的归档目录
-bash-4.2$ll/data/pg_archive/ total49152 -rw-------.1postgrespostgres16777216Apr2114:04000000010000000000000001 -rw-------.1postgrespostgres16777216Apr2114:04000000010000000000000002 -rw-------.1postgrespostgres16777216Apr2114:04000000010000000000000003
至此,归档备份已经完成,下面我们要介绍利用归档进行恢复。
模拟从归档进行PITR恢复
PITR恢复是基于文件系统备份和wal文件的备份,因此首先我们需要个基础备份,然后在此基础备份上对wal归档日志进行回放。具体步骤如下:
1.使用pg_basebackup进行基础备份
pg_basebackup使用replication复制协议,因此需要在源库上配置pg_hba.conf文件以允许replication,无论是本地还是通过网络。
vimpg_hba.conf #添加以下两行,允许本地和网络上的replication用于pg_basebackup hostreplicationrep127.0.0.1/32md5 hostreplicationrep10.10.10.61/8md5 #重载 pg_ctlreload-D/data/pgsql/data
添加完毕后请重载pgsql
在备份库上执行pg_basebackup进行远程的基础备份
-bash-4.2$pg_basebackup-D/data/pgsql/data-Fp-Xs-v-P-h10.10.10.61-p5432-Urep Password: transactionlogstartpoint:0/5000020 pg_basebackup:startingbackgroundWALreceiver 26664/26664kB(100%),1/1tablespace transactionlogendpoint:0/50000E0 pg_basebackup:waitingforbackgroundprocesstofinishstreaming... pg_basebackup:basebackupcompleted
-D表示接受基础备份的目录,我们将基础备份放到/data/pgsql/data
-X参数,在备份完成之后,会到主库上收集pg_basebackup执行期间产生的WAL日志,在9.2版本之后支持-Xs即stream形式,这种模式不需要收集主库的WAL文件,而能以stream复制方式直接追赶主库。
2.修改备库上配置文件
由于所有的配置文件是从源库上的备份过来的,因此我们需要修改:
vimpostgresql.conf 屏蔽以下两行 #archive_mode=on #archive_command='ssh192.168.3.139test!-f/data/pg_archive/%f&&scp%p192.168.3.139:/data/pg_archive/%f'
3.查看源库上的时间确认需要的恢复时间点
postgres=#select*fromt1; id|create_time ----+--------------------- 1|2016-04-2113:49:34 2|2016-04-2113:49:48 3|2016-04-2114:00:22 4|2016-04-2114:00:25 5|2016-04-2114:49:11 6|2016-04-2114:49:14 7|2016-04-2114:49:17 (4rows)
由于此次基础备份是在“4|2016-04-2114:00:25”这条记录后归档,而后面的5,6,7三条记录是在基础备份后生成的,因此若恢复5,6,7中的记录需要在基础备份上通过回放5,6,7的归档日志达到。
在此我们要将数据恢复到6这条记录下,需要在recovery.conf中做如下设置:
cp/usr/share/pgsql/recovery.conf.sample/data/pgsql/data/recovery.conf vimrecovery.conf restore_command='cp/data/pg_archive/%f%p' recovery_target_time='2016-04-2114:49:14'
**注意:**recovery.conf中standby_mode要为off,否则备份库将会以备库身份启动,而不是即时恢复。
4.启动备份库
备份库启动过程中,会进行PITR恢复到指定的时间点
pg_ctlstart-D/data/pgsql/data #查看日志 vim/data/pgsql/pg_log/postgresql-Thu.log LOG:databasesystemwasinterrupted;lastknownupat2016-04-2114:34:29CST LOG:startingpoint-in-timerecoveryto2016-04-2114:49:14+08 LOG:restoredlogfile"000000010000000000000005"fromarchive LOG:redostartsat0/5000020 LOG:consistentrecoverystatereachedat0/50000E0 LOG:restoredlogfile"000000010000000000000006"fromarchive LOG:recoverystoppingbeforecommitoftransaction1898,time2016-04-2114:49:16.635744+08 LOG:redodoneat0/6000398 LOG:lastcompletedtransactionwasatlogtime2016-04-2114:49:13.786388+08 cp:cannotstat‘/data/pg_archive/00000002.history':Nosuchfileordirectory LOG:selectednewtimelineID:2 cp:cannotstat‘/data/pg_archive/00000001.history':Nosuchfileordirectory LOG:archiverecoverycomplete LOG:autovacuumlauncherstarted LOG:databasesystemisreadytoacceptconnections #查看数据 postgres=#select*fromt1; id|create_time ----+--------------------- 1|2016-04-2113:49:34 2|2016-04-2113:49:48 3|2016-04-2114:00:22 4|2016-04-2114:00:25 5|2016-04-2114:49:11 6|2016-04-2114:49:14 (6rows)
7.查看备份库pg_xlog
-bash-4.2$llpg_xlog total49160 -rw-------.1postgrespostgres16777216Apr2115:00000000010000000000000005 -rw-------.1postgrespostgres16777216Apr2115:00000000010000000000000006 -rw-------.1postgrespostgres16777216Apr2115:00000000020000000000000006 -rw-------.1postgrespostgres64Apr2115:0000000002.history drwx------.2postgrespostgres4096Apr2115:00archive_status -bash-4.2$catpg_xlog/00000002.history 1000000010000000000000006before2016-04-2114:49:16.635744+08
从pg_xlog我们看到设置好recovery.conf文件后,启动数据库,将会产生新的timeline,id=2,而且会生成一个新的history文件00000002.history,里面记录的是新时间线2从什么时间哪个时间线什么原因分出来的,该文件可能含有多行记录。
另外,恢复的默认行为是沿着与当前基本备份相同的时间线恢复。如果你想恢复到某些时间线,你需要指定的recovery.conf目标时间线recovery_target_timeline,不能恢复到早于基本备份分支的时间点。
注意:如果恢复过一次,并重新设置recovery_target_time,重新启动触发恢复,并不会基于时间线1进行恢复,而是基于时间线2进行恢复的,但是此时间线上在/data/pg_archive/并没有时间线为2的归档日志,因此会报错。
补充:postgres修改归档模式
步骤一:
修改postgresql的配置文件(postgresql.conf)
wal_level=hot_standby archive_mode=on archive_command='DATE=`date+%Y%m%d`;DIR="/home/postgres/arch/$DATE";(test-d$DIR||mkdir-p$DIR)&&cp%p$DIR/%f'
ps:%p是指相对路径%f是指文件名
步骤二:创建归档路径
mkdir-p/home/postgres/arch chown-Rpostgres:postgres/home/postgres/arch
步骤三:重启数据库
步骤四:验证归档是否正常
postgres=#checkpoint; CHECKPOINT postgres=#selectpg_switch_xlog(); pg_switch_xlog ---------------- 1/760000E8 (1row) postgres@ubuntu:~$cd/home/postgres/data/data_1999/arch/ postgres@ubuntu:~/data/data_1999/arch$ls 20150603 postgres@ubuntu:~/data/data_1999/arch$cd20150603/ postgres@ubuntu:~/data/data_1999/arch/20150603$ls 000000010000000100000074000000010000000100000075000000010000000100000076
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。