如何打造PostgreSQL闪回环境

在 PostgreSQL 数据库;目前是不支持类似 Oracle 闪回特性;我们知道 Oracle 闪回特性在数据恢复是非常简单给力。增加数据库操作人员(开发,DBA)的容错率。Oracle 闪回特性使用场景:

  • flashback database: 数据库闪回;多用于数据库恢复;数据库,用户,表空间误删。
  • flashback table : 表闪回;用于数据表恢复;数据表误删。
  • flashback query : 闪回查询;应用于修复误操作数据。

对于 PostgreSQL 闪回;校长(德哥)有写过一系列的文章PostgreSQL flashback(闪回)功能实现与介绍;如今我取巧实现 PostgreSQL 闪回特性。原理参考我之前的文章PostgreSQL恢复误删数据

  • 支持在线数据库恢复(不推荐),多用于数据表恢复,修复误操作数据。
  • 支持多次闪回操作;在 flashback query 中恢复的时间点不是很理想;可以重新设定时间点再闪回操作一次。

一. flashback 所需命令

实现 flashback 就是一个有效的数据库备份/恢复。

  • 备份操作命令有 scp/cp, pg_basebackup, pg_rman。我选 pg_basebackup。因为pg_basebackup 支持异构备份。意味着可以在同一台服务器在 cp 一个 PostgreSQL 实例。即可以在一台服务器上实现闪回。
  • 恢复操作有 copy 或者 pg_dump 命令。

二. flashback 所需条件

实现 flashback 可以是在线服务器上操作,也可以是在另一台服务器上操作。换句话说:可以是一台服务器或者是两台服务器来实现。在一台服务器上需要更改数据库端口。由于本环境有清理目录操作;避免在在线服务器上误删目录。所以建议用两条服务器来实现。

三. flashback 搭建原理

本文档采用两台服务器来实现。两台服务器时间校准,免密码登录。

  • 正式数据库环境:192.168.1.201
  • 闪回数据库环境:192.168.1.202
    当然闪回数据库环境可在正式环境下;配置文档精彩再续

3.1 创建脚本cleandir.sh

cleandir脚本用于在pg_basebackup备份前;先清空备份所需的路径

psql -h 192.168.1.201 -p $PGPORT -t -A -n -c"SELECT pg_catalog.pg_tablespace_location(oid) AS "Location" FROM pg_catalog.pg_tablespace where spcname not in ('pg_default','pg_global')" -o tablespace_location.txt
awk '{print "rm -rf " $1}' tablespace_location.txt > cleandir.sh
echo "rm -rf $PGDATA" >> cleandir.sh

3.2 创建备份脚本pg_backup.sh

采用pg_basebackup备份;

cleandir.sh
pg_basebackup -F p --progress -D $PGDATA -h 192.168.1.201 -p $PGPORT -U replica

加入定时任务 crontab 中 例如:每天凌晨过5分执行备份

5 0 * * * pg_backup.sh

3.3 创建配置文件recovery.conf模板

执行闪回查询/数据库恢复。多用时间点进行恢复即(PITR)

restore_command = 'scp postgres@192.168.1.201:**/%f %p'
recovery_target_time = '2018-11-10 10:33:12'

3.4 创建恢复脚本pg_flashback.sh

pg_flashback.sh 脚本用于数据库误操作实现闪回到某个时间点。支持多次闪回。执行闪回 之前;需要配置 recovery.conf 中的 “recovery_target_time” 时间点。即恢复到哪个时间点。
第一次执行;执行

pg_flashback.sh 1

往后执行闪回;通称再次执行;执行命令

pg_flashback.sh 2

当然往后加也行例如:pg_flashback.sh 3
pg_flashback.sh脚本如下

##===========================================================  
##   pg_flashback.sh                
##   created by lottu           
##   2018/11/07    
##   usage: pg_flashback.sh 1                          
##============================================================  
#!/bin/bash
PGHOME=/opt/pgsql96
PGDATA=/data/postgres/data              
LANG=en_US.utf8
PGPORT=5432
PGUSER=postgres
PGDATABASE=postgres
PG_BACK_HOST_IP=192.168.1.202
E_BADARGS=65
E_FAIL=66

if [ $# -ne 1 ];then
 echo "Usage: `basename $0` Please invoke this script with one command-line arguments"
 exit $E_BADARGS
fi
flashback_path=/data/flash_back
if [ $1 -eq 1 ];then
 echo "Info: backup backupset"
 backup.sh
else
 rebackup.sh
fi 
echo "Info: edit recovery.conf"
#scp recovery.conf postgres@192.168.1.202:$PGDATA
cp /home/postgres/recovery.conf $PGDATA
echo "Info: begin start database"
pg_ctl start -l /home/postgres/log/pg_server.log
if [ $? -eq 0 ];then
 echo "Info: start database succes"
 sleep 10
 psql -h $PG_BACK_HOST_IP -p 5432 postgres postgres -c "select pg_xlog_replay_resume()"
else
 echo "[Error]: start database fail"
 exit $E_FAIL
fi 

四. flashback 实验验证

4.1 验证目的

  • 验证是否可以闪回/恢复
  • 验证是否可以多次操作闪回
  • 验证在闪回的过程中;正式环境是否正常对外服务

4.2 实验操作

4.2.1 备份数据库

执行pg_backup.sh脚本。部署成功了是没这个操作。因为每天都有定时备份。

[postgres@Postgres202 ~]$ pg_backup.sh 
waiting for server to shut down......... done
server stopped
322503/322503 kB (100%), 4/4 tablespaces

4.2.2 模拟误操作

lottu=# create table lottu as select * from lottu01 ;
SELECT 4
lottu=# select * from lottu;
  id  | text  
------+-------
 1001 | lottu
 1004 | rax
 1002 | world
 1003 | world
(4 rows)
-- 获取时间点;这个时间点“2018-11-10 14:56:56”是我目标恢复时间点。表lottu有4条记录。
lottu=# select now();
             now              
------------------------------
 2018-11-10 14:56:56.30188+08
(1 row)
-- 在时间点“2018-11-10 14:57:51”;误操作1 清理表lottu的记录
lottu=# delete from lottu;
DELETE 4
lottu=# select now();
              now              
-------------------------------
 2018-11-10 14:57:51.891931+08
(1 row)

-- 误操作2 删除表lottu。
lottu=# drop table lottu;
DROP TABLE
  • 获取时间点;这个时间点“2018-11-10 14:56:56”是我目标恢复时间点。表lottu有4条记录。
  • 在时间点“2018-11-10 14:57:51”;误操作1 清理表lottu的记录
  • 误操作2 删除表lottu。

4.2.3 闪回操作

我们先在配置文件 recovery.conf 中的参数“recovery_target_time” 设置为 “2018-11-10 14:57:51”。执行闪回pg_flashback.sh 1

[postgres@Postgres202 ~]$ pg_flashback.sh 1
Info: backup backupset
Info: edit recovery.conf
Info: begin start database
server starting
Info: start database succes
psql: FATAL:  the database system is starting up

闪回数据库成功启动;登录查看表lottu情况:表数据未找回;这不是我所需闪回的目标

[postgres@Postgres202 ~]$ psql lottu lottu
psql (9.6.0)
Type "help" for help.

lottu=# \d lottu
     Table "lottu.lottu"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | 
 name   | text    | 

lottu=# select * from lottu;
 id | name 
----+------
(0 rows)

在配置文件 recovery.conf 中的参数“recovery_target_time” 设置为 “2018-11-10 14:56:56”。再执行闪回pg_flashback.sh 2

[postgres@Postgres202 ~]$ pg_flashback.sh 2
Info: edit recovery.conf
Info: begin start database
server starting
Info: start database success
psql: FATAL: the database system is starting up

再次闪回也成功了。我们在看下表lottu的情况

[postgres@Postgres202 ~]$ psql lottu lottu
psql (9.6.0)
Type "help" for help.

lottu=# \d lottu
     Table "lottu.lottu"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | 
 name   | text    | 

lottu=# select * from lottu;
  id  | name  
------+-------
 1001 | lottu
 1004 | rax
 1002 | world
 1003 | world
(4 rows)

表 lottu 的数据成功找回。在使用 pg_dump 导出表 lottu 的表结构和数据的脚本;

[postgres@Postgres202 ~]$ pg_dump -d lottu -t lottu.lottu  -f lottu.sql
[postgres@Postgres202 ~]$ scp lottu.sql postgres@192.168.1.201:/home/postgres

再到正式数据库上执行

[postgres@Postgres201 ~]$ psql lottu lottu 
psql (9.6.0)
Type "help" for help.

lottu=# \i lottu.sql
SET
SET
SET
SET
SET
SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
COPY 4
lottu=# \d lottu
     Table "lottu.lottu"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | 
 name   | text    | 

lottu=# select * from lottu;
  id  | name  
------+-------
 1001 | lottu
 1004 | rax
 1002 | world
 1003 | world
(4 rows)

在整个闪回过程;除了最后一步是在正式服务器上执行。前面其他操作都是在闪回数据库操作。

4.3 实验结论

  • 可以闪回
  • 可以多次操作
  • 不影响正式环境

五. 其他实现方式参考

PostgreSQL flashback(闪回) 功能实现与介绍

六. 不足

  • 不推荐使用这种方式恢复数据库。多用于ddl/dml误操作恢复。

七. 代码下载

链接:https://pan.baidu.com/s/1j8ZNj3yjxj82MnomzxQkfA
提取码:j4xd

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容