pg_lightool-postgres数据库基于wal日志的坏页修复

Download

2019/12/05

李传成Contributor

瀚高软件内核研发工程师,主要的研究wal日志,并基于对wal日志的理解开发了wal相关的开源项目walminer和pg_lightool

在大象的世界里,砥砺前行,move ahead。

博客:https://my.oschina.net/lcc1990

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]$ 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                        //是否保存现有表文件(默认保存)

五、使用限制

  1. 当前只能解析同一个时间线的xlog,如果没有足够多的wal日志,无法正确恢复目标页。
  2. 当前只能完成table数据的块恢复。
  3. 此为个人兴趣项目,没有经过完整的测试,请谨慎填写入参。
  4. 项目是在pg10.4上做的开发,没有对其他环境做测试

六、bug提交

    如有bug可以在码云上提交,也可联系我(lchch1990@sina.cn)

0