2019-4-10更新: blockrecover命令可以依托pg_basebackup生成的基础备份完成坏块修复(使用-r参数即可)
一、前言
当前postgres数据库可选的恢复工具(PITR,pg_rman)都需要一个基础备份。恢复原理就是以基础备份为base,通过重演wal日志使数据库达到一个用户满意 的状态。
如果没有基础备份,那么数据库一旦有页损坏,那么这个页的数据会恢复困难。实际上在wal日志足够多的情况下,是可以做到不依靠基础备份,就能完成坏块恢复的。鉴于这个情况和一些工作经验,我创建了一个pg_lightool项目,此项目中含有一个blockrecover工具,它不需要基础备份,只需要扫描wal日志就可 以完成坏块的恢复,当然这需要相对较完整的wal日志。
废不多说,下面就介绍一下这款工具的使用情况。
二、源码
下载地址:
目前只有源码编译安装版本。
三、代码编译安装
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 TABLEpostgres=# insert into t3 (i,j,k) select generate_series(1,157),0,'qazwsxedcr';INSERT 0 157postgres=# insert into t3 (i,j,k) select generate_series(1,157),1,'qazwsxedcr';INSERT 0 157postgres=# insert into t3 (i,j,k) select generate_series(1,157),2,'qazwsxedcr';INSERT 0 157postgres=# insert into t3 (i,j,k) select generate_series(1,157),3,'qazwsxedcr';INSERT 0 157postgres=# 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 stopwaiting for server to shut down....2018-08-21 12:39:23.298 CST [2764] LOG: received fast shutdown request2018-08-21 12:39:23.299 CST [2764] LOG: aborting any active transactions2018-08-21 12:39:23.300 CST [2764] LOG: worker process: logical replication launcher (PID 2772) exited with exit code 12018-08-21 12:39:23.310 CST [2766] LOG: shutting down2018-08-21 12:39:23.560 CST [2764] LOG: database system is shut down doneserver stopped
模拟数据页损坏
[lchch@yfslcentos71 13211]$ vi 16390
之前查询了t3表的relfilenode是16390,vim打开16390文件后,进行一些破坏性修改。
数据库启动后表无法正确查询
[lchch@yfslcentos71 13211]$ psqlpsql (10.4)Type "help" for help.postgres=# select * from t3postgres-# ;2018-08-21 12:45:05.706 CST [3127] ERROR: invalid page in block 0 of relation base/13211/163902018-08-21 12:45:05.706 CST [3127] STATEMENT: select * from t3 ;ERROR: invalid page in block 0 of relation base/13211/16390postgres=#
使用工具进行坏页修复
注意:
此次测试没有闭库执行工具命令,实际时建议闭库使用。
//第一次执行:[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//执行完成后再次查询t3postgres=# select * from t3;2018-08-21 12:54:25.272 CST [3127] ERROR: invalid page in block 1 of relation base/13211/163902018-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//执行完成后再次查询t3postgres=# select * from t3;2018-08-21 12:54:42.713 CST [3127] ERROR: invalid page in block 2 of relation base/13211/163902018-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//执行完成后再次查询t3postgres=# 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 | qazwsxedcrpostgres=#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 postgresUsage: 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)