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

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

五、使用限制

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

六、bug提交

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

    原文作者:数据库基础
    原文地址: https://my.oschina.net/lcc1990/blog/1931485
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞