2019-4-10更新: blockrecover命令可以依托pg_basebackup生成的基础备份完成坏块修复(使用-r参数即可)
一、前言
当前postgres数据库可选的恢复工具(PITR,pg_rman)都需要一个基础备份。恢复原理就是以基础备份为base,通过重演wal日志使数据库达到一个用户满意 的状态。
如果没有基础备份,那么数据库一旦有页损坏,那么这个页的数据会恢复困难。实际上在wal日志足够多的情况下,是可以做到不依靠基础备份,就能完成坏块恢复的。鉴于这个情况和一些工作经验,我创建了一个pg_lightool项目,此项目中含有一个blockrecover工具,它不需要基础备份,只需要扫描wal日志就可 以完成坏块的恢复,当然这需要相对较完整的wal日志。
废不多说,下面就介绍一下这款工具的使用情况。
二、源码
下载地址:http://gitee.com/movead/pg_lightool
目前只有源码编译安装版本。
三、代码编译安装
1.首先需要配置postgres的PATH路径
2.进入下载的代码的pg_lightool目录
3.make;make install;
这样就pg_lightool工具就成功安装到postgres的bin目录下了。
四、工具使用
创建测试表,并关闭数据库
postgres=# create table t3(i int,j int,k varchar);
CREATE TABLE
postgres=# insert into t3 (i,j,k) select generate_series(1,157),0,'qazwsxedcr';
INSERT 0 157
postgres=# insert into t3 (i,j,k) select generate_series(1,157),1,'qazwsxedcr';
INSERT 0 157
postgres=# insert into t3 (i,j,k) select generate_series(1,157),2,'qazwsxedcr';
INSERT 0 157
postgres=# insert into t3 (i,j,k) select generate_series(1,157),3,'qazwsxedcr';
INSERT 0 157
postgres=# select count(*) from t3;
count
-------
628
(1 row)
postgres=# select count(*) from t3 where j = 0;
count
-------
157
(1 row)
postgres=# select count(*) from t3 where j = 1;
count
-------
157
(1 row)
postgres=# select count(*) from t3 where j = 2;
count
-------
157
(1 row)
postgres=# select count(*) from t3 where j = 3;
count
-------
157
(1 row)
postgres=# select count(*) from t3 where j = 4;
count
-------
0
(1 row)
postgres=# \q
[lchch@yfslcentos71 20180728]$ pg_ctl stop
waiting for server to shut down....2018-08-21 12:39:23.298 CST [2764] LOG: received fast shutdown request
2018-08-21 12:39:23.299 CST [2764] LOG: aborting any active transactions
2018-08-21 12:39:23.300 CST [2764] LOG: worker process: logical replication launcher (PID 2772) exited with exit code 1
2018-08-21 12:39:23.310 CST [2766] LOG: shutting down
2018-08-21 12:39:23.560 CST [2764] LOG: database system is shut down
done
server stopped
模拟数据页损坏
[lchch@yfslcentos71 13211]$ vi 16390
之前查询了t3表的relfilenode是16390,vim打开16390文件后,进行一些破坏性修改。
数据库启动后表无法正确查询
[lchch@yfslcentos71 13211]$ psql
psql (10.4)
Type "help" for help.
postgres=# select * from t3
postgres-# ;
2018-08-21 12:45:05.706 CST [3127] ERROR: invalid page in block 0 of relation base/13211/16390
2018-08-21 12:45:05.706 CST [3127] STATEMENT: select * from t3
;
ERROR: invalid page in block 0 of relation base/13211/16390
postgres=#
使用工具进行坏页修复
注意:
此次测试没有闭库执行工具命令,实际时建议闭库使用。
//第一次执行:
[lchch@yfslcentos71 walbak]$ pg_lightool blockrecover -f 0/13211/16390 -b 0 -w /work/opt/postgres/20180728/walbak/ -D /work/opt/postgres/20180728/data
BlockRecover:file->/work/opt/postgres/20180728/data/base/13211/16390,page:0
//执行完成后再次查询t3
postgres=# select * from t3;
2018-08-21 12:54:25.272 CST [3127] ERROR: invalid page in block 1 of relation base/13211/16390
2018-08-21 12:54:25.272 CST [3127] STATEMENT: select * from t3;
ERROR: invalid page in block 1 of relation base/13211/16390
//第二次执行
[lchch@yfslcentos71 walbak]$ pg_lightool blockrecover -f 0/13211/16390 -b 1 -w /work/opt/postgres/20180728/walbak/ -D /work/opt/postgres/20180728/data
BlockRecover:file->/work/opt/postgres/20180728/data/base/13211/16390,page:1
//执行完成后再次查询t3
postgres=# select * from t3;
2018-08-21 12:54:42.713 CST [3127] ERROR: invalid page in block 2 of relation base/13211/16390
2018-08-21 12:54:42.713 CST [3127] STATEMENT: select * from t3;
ERROR: invalid page in block 2 of relation base/13211/16390
//第三次执行
[lchch@yfslcentos71 walbak]$ pg_lightool blockrecover -f 0/13211/16390 -b 2 -w /work/opt/postgres/20180728/walbak/ -D /work/opt/postgres/20180728/data
BlockRecover:file->/work/opt/postgres/20180728/data/base/13211/16390,page:2
//执行完成后再次查询t3
postgres=# select * from t3;
i | j | k
-----+---+------------
1 | 0 | qazwsxedcr
2 | 0 | qazwsxedcr
3 | 0 | qazwsxedcr
4 | 0 | qazwsxedcr
5 | 0 | qazwsxedcr
6 | 0 | qazwsxedcr
7 | 0 | qazwsxedcr
8 | 0 | qazwsxedcr
9 | 0 | qazwsxedcr
10 | 0 | qazwsxedcr
11 | 0 | qazwsxedcr
postgres=#
postgres=# select count(*) from t3 where j = 0;
count
-------
157
(1 row)
postgres=# select count(*) from t3 where j = 1;
count
-------
157
(1 row)
postgres=# select count(*) from t3 where j = 2;
count
-------
157
(1 row)
3.至此完成了坏块的恢复。
4.参数说明
[lchch@yfslcentos71 ~]$ pg_lightool -?
pg_lightool is a light tool of postgres
Usage:
pg_lightool OPTION blockrecover //blockrecover工具
pg_lightool OPTION walshow //walshow工具(未实现)
Common Options:
-V, --version //显示版本
-l, --log //是否打印log
-f, --relnode=spcid/dbid/relfilenode //指定要修复的表
-b, --block=n1[,n2,n3] //指定要修复的页
-w, --walpath=walpath //wal日志读取位置
-D, --pgdata=datapath //数据目录
-i, --immediate //是否保存现有表文件(默认保存)
五、使用限制
- 当前只能解析同一个时间线的xlog,如果没有足够多的wal日志,无法正确恢复目标页。
- 当前只能完成table数据的块恢复。
- 此为个人兴趣项目,没有经过完整的测试,请谨慎填写入参。
- 项目是在pg10.4上做的开发,没有对其他环境做测试
六、bug提交
如有bug可以在码云上提交,也可联系我(lchch1990@sina.cn)