PITR: 使用 ZFS 的 Snapshots 制定 PITR 方案

一 环境信息

主节点
IP 192.168.2.200
系统 RHEL6.2

备节点
IP 192.168.2.40
系统 FreeBSD 10.0

二 FreeBSD 安装 pg 备节点

环境变量 ~/.prpfile

1
2
3
4
5
6
7
8
9
10
11
12
export PGPORT=1921  
export PGUSER=postgres
export PGDATA=/database/pg93/pg_root
export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.3.5
export PGPOOL_HOME=/opt/pgpool
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib # 这里的设置可能要改下
export DATE=`date +"%Y%m%d%H%M"`
export PATH=/opt/pgbouncer/bin:$PGHOME/bin:$PGPOOL_HOME/bin:$PATH:.
export MANPATH=$PGHOME/share/man:$MANPATH
alias rm='rm -i'
alias ll='ls -lh'

编译并安装

1
2
3
root@francs:/ # ./configure --prefix=/opt/pgsql9.3.5  --with-pgport=1921 --with-wal-blocksize=16    
root@francs:/ # gmake
root@francs:/ # gmake install

创建数据目录并赋权

1
2
3
4
5
6
7
8
9
root@francs:/ # zfs create -o mountpoint=/database/ zp_db/database  

root@francs:~ # zfs list -r zp_db
NAME USED AVAIL REFER MOUNTPOINT
zp_db 174M 29.1G 31K /zp_db
zp_db/database 31K 29.1G 31K /database/
zp_db/opt 174M 29.1G 174M /opt

root@francs:/ # chown -R francs:francs /database

编辑密码文件

1
2
[francs@francs ~]$ cat ~/.pgpass  
192.168.2.200:1921:replication:repuser:rep123us345er

备注:同时修改主节点的 pg_hba.conf。

pg_basebackup 创建流复制备节点

1
2
3
4
5
6
[francs@francs ~]$ pg_basebackup -D /database/pg93/pg_root -Fp  -Xs  -v -P -h 192.168.2.200  -p 1921  -U repuser

recovery.conf 配置
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.2.200 port=1921 user=repuser'

pg_ctl 启动备节点

1
2
3
4
5
6
7
8
[francs@francs /database/pg93/pg_root]$ pg_ctl start  
server starting

[francs@francs /database/pg93/pg_root]$ FATAL: XX000: could not create semaphores: No space left on device
DETAIL: Failed system call was semget(1921021, 17, 03600).
HINT: This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL s consumption of semaphores by reducing its max_connections parameter.
The PostgreSQL documentation contains more information about configuring your system for PostgreSQL.
LOCATION: InternalIpcSemaphoreCreate, pg_sema.c:125

备注:启动报错,内核设置 kernel 的共享内存不够,设置以下即可。

配置/boot/loader.conf

1
2
3
kern.ipc.semmni=512  
kern.ipc.semmns=1024
kern.ipc.semmnu=256

配置/etc/sysctl.conf

1
2
3
sysctl kern.ipc.shmall=32768  
sysctl kern.ipc.shmmax=134217728
sysctl kern.ipc.semmap=256

备注:这些设置满足实验目的,reboot 生效。

三 生成快照

create_snap.sh 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@francs:/usr/local/bin # cat /usr/local/bin/create_snap.sh  
#!/usr/local/bin/bash
# create snapshot every 1 minutes

while true
do
current_time=`date "+%Y%m%d_%H%M%S"`
zfs snapshot zp_db/database@"$current_time"

if [ $? -ne 0 ]; then
echo `date "+%Y-%m-%d %H:%M:%S"` "zp_db/database snapshot generates failed!"
break
fi

echo `date "+%Y-%m-%d %H:%M:%S"` "zp_db/database snapshot generates successfuly!" >> /tmp/snapshot.log
sleep 60
done

备注: 创建一个生成快照的脚本,每分钟创建一个快照。

开启脚本

1
nohup /usr/local/bin/create_snap.sh 2>&1  &

打开 .zfs 隐藏目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@francs:/usr/local/bin # ls -a /database  
. .. pg93

root@francs:/usr/local/bin # zfs set snapdir=visible zp_db/database

root@francs:/usr/local/bin # ls -a /database
. .. .zfs pg93

root@francs:~ # ll /database/.zfs/snapshot/
total 140
drwxr-xr-x 3 francs francs 3 10 9 21:11 20141010_114052/
drwxr-xr-x 3 francs francs 3 10 9 21:11 20141010_134732/
drwxr-xr-x 3 francs francs 3 10 9 21:11 20141010_135359/
drwxr-xr-x 3 francs francs 3 10 9 21:11 20141010_140045/
drwxr-xr-x 3 francs francs 3 10 9 21:11 20141010_140413/
drwxr-xr-x 3 francs francs 3 10 9 21:11 20141010_140513/
....

备注:查看快照有两种方式,一种是通过” zfs list -t snapshot” 命令, 另一种是查看 .zfs 隐藏目录下,可以打开数据集的 snapdir 属性使 .zfs 目录可见。

四 恢复测试

主节点

1
2
3
4
5
6
7
[pg93@db1 script]$ cat pitr_insert.sh  
#!/bin/bash

for((i=1;i>0;i=1)) do
psql -d postgres -U postgres -c "insert into test_pitr (name) values('test_pitr');"
sleep 10;
done

备注:主节点跑一个数据插入脚本,每 10 秒向主节点插入一条数据。通过这个程序,测试 ZFS 是否能做基于时间点的数据恢复。

表结构如下

1
2
3
4
5
6
Table  "public.test_pitr"  
Column | Type | Modifiers
-------------+--------------------------------+--------------------------------------------------------
id | integer | not null default nextval('test_pitr_id_seq'::regclass)
name | character varying(64) |
create_time | timestamp(0) without time zone | default clock_timestamp()

zfs clone

1
2
3
4
5
6
7
8
root@francs:/usr/local/bin # zfs clone zp_db/database@20141010_141412 zp_db/pitr141412  

root@francs:/usr/local/bin # zfs list -r zp_db
NAME USED AVAIL REFER MOUNTPOINT
zp_db 1.14G 28.1G 32K /zp_db
zp_db/database 990M 28.1G 947M /database/
zp_db/opt 174M 28.1G 174M /opt
zp_db/pitr141412 1K 28.1G 947M /zp_db/pitr141412

备注: 我们将数据恢复到 2014-10-10 14-14-12 时刻,新的数据目录为 /zp_db/pitr141412,可以看到这个目录空间使用为 1K ,几乎没占用额外空间。

修改 recovery.conf, postgresql.conf
由于此台上已经跑了一个 pg 备库,为了不和之前的备节点信息重复,需要修改 postgresql.conf 里的 port 参数,并且最好是移走 recovery.conf 参数,将恢复的数据库以主库模式启动。

启动恢复目录的 pg

1
[francs@francs ~]$ pg_ctl start -D /zp_db/pitr141412/pg93/pg_root

五 数据验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[francs@francs /zp_db/pitr141412/pg93/pg_root/pg_log]$ psql -p 1922  
psql (9.3.5)
Type "help" for help.

postgres=# select * from test_pitr order by id desc limit 3;
id |name | create_time
------+-----------+---------------------
7909 | test_pitr | 2014-10-10 14:14:08
7908 | test_pitr | 2014-10-10 14:13:58
7907 | test_pitr | 2014-10-10 14:13:47
(3 rows)

postgres=# select count(*) from test_pitr;
count
-------
935
(1 row)

备注:数据成功恢复到 2014-10-10 14-14-12 时刻。

六 总结

利用 ZFS 的 snapshot 和 clone 功能能够轻松满足 PostgreSQL 数据库的 PITR 需求,而且具有实施简单,低成本,恢复时间短的优点。

七 参考

原创文章,作者:745907710,如若转载,请注明出处:https://blog.ytso.com/239589.html

(0)
上一篇 2022年2月12日
下一篇 2022年2月12日

相关推荐

发表回复

登录后才能评论