从旧的完整转储和/或最新的基本目录和其他保存的文件中恢复PostgreSQL-9.6数据库



我正试图从以下一些数据库中恢复/拯救数据库:

  • 我在PGDATA/base(/var/lib/postgresql/9.6/main/base/)中有所有最近的文件,但我没有完整的/var/lib/postgresql/9.6/main/

  • 我有所有来自旧备份(没有太大不同)转储的文件,我在新安装的PostgreSQL-9.6中恢复了这些文件。

  • 我有很多从硬盘驱动器(从ddrescue)中拯救的文件,我得到了数千个没有名字的文件(有一个"#",然后有一个数字,并且在丢失+找到的目录中),所以,例如:

    • 我有pg_class文件
    • 我有pg_clog目录和0000文件

编辑:

可能我有pg_xlog的内容,但我没有文件的名称。我有5个文件大小16777216字节:

#288294 (date 2019-04-01)
#288287 (date 2019-05-14)
#288293 (date 2019-07-02)
#261307 (date 2019-11-27)
#270185 (date 2020-01-28)

我的旧垃圾箱是2019-04-23,所以第一个可能是一样的吗?

所以我的下一步是尝试用pg_xlogdump读取这些文件和/或尝试用这些名称文件命名它们(以开头00000001000000000000000A,并将它们放在新的pg_xlog目录中,我看到命名它们的系统文件可能是?)。我还意识到最后一个有硬盘崩溃当天的日期,所以我有最后一个。

我从硬盘驱动器(损坏)中拯救的PGDATA/base目录包含目录1124061240737972,其中有很多文件。我向pg_filedump -fi确认我的更新数据存储在目录37972中的文件中。

相同(但旧的)数据存储在恢复转储中目录PGDATA/base/16387中的文件中。

我试图直接将文件从一个复制到另一个,在旧数据库上混合更新的数据,但不起作用。在解决了权限错误后,我可以以这种方式进入"弗兰肯斯坦"数据库:

postgres@host:~$ postgres --single -P -D /var/lib/postgresql/9.6/main/ dbname

我试着做一些事情,比如重新索引,但我得到了这个错误:

PostgreSQL stand-alone backend 9.6.16
backend> reindex system dbname;
ERROR:  could not access status of transaction 136889
DETAIL:  Could not read from file "pg_subtrans/0002" at offset 16384: Success.
CONTEXT:  while checking uniqueness of tuple (1,7) in relation "pg_toast_2619"
STATEMENT:  reindex system dbname;

当然,pg_subtrans/0002文件是"弗兰肯斯坦"的一部分,不是一个好的文件(因为我还没有找到它,不是用那个名字),所以我尝试:先复制另一个看起来相似的文件,然后用dd生成8192个零到那个文件,在这两种情况下,我都会得到相同的错误(如果文件不存在,就得到DETAIL: Could not open file "pg_subtrans/0002": No such file or directory.)。不管怎样,我不知道那个文件应该是什么。你认为我可以从其他文件中获取数据吗?或者我可以用一些工具找到丢失的文件吗?因此,对于目录pg_subtrans/0000中的另一个文件,pg_filedump显示为空。

额外注意:我发现了这篇有用的博客文章,其中谈到了使用pg_filedumppg_class的文件、reindex system和其他工具从刚刚拯救的文件中恢复,但我很难理解如何将其适应我的具体而简单的问题(我认为我的问题更容易,因为我有一个转储):https://www.commandprompt.com/blog/recovering_a_lost-and-found_database/

经过4个部分:之后,我们终于完全恢复了基于PGDATA/base/37972目录的数据库

  1. 检查和";greping";与pg_filedump -fi对应的文件每个表。致";greping";我们做剧本更容易。

    #!/bin/bash
    for filename in ./*; do
    echo "$filename"
    pg_filedump -fi "$filename"|grep "$1"
    done
    

    注意:仅适用于小字符串

  2. 执行伟大的工具pg_filedump -D-D是一个新的选项(来自postgresql-filedump版本≥10),使用给定的逗号分隔的类型列表来解码元组。

    因为我们制作了数据库,所以我们知道类型;只是";需要给出一个以逗号分隔的与表相关的类型列表。我写了";只是";因为在某些情况下可能会有点复杂。我们的一个表需要这种命令:

pg_filedump -D text,text,text,text,text,text,text,text,timestamp,text,text,text,text,int,text,text,int,text,int,text,text,text,text,text,text,text,text,text,text,int,int,int,int,int,int,int,int,text,int,int 38246 | grep COPY > restored_table1.txt

来自pg_filedump -D手册:

支持的类型:

  • bigint

  • 双串行

  • bool

  • 字符

  • charN—char(n)

  • 日期

  • 浮动

  • float4

  • float8

  • int

  • json

  • macaddr

  • 名称

  • oid

  • 真实

  • 串行

  • smallint

  • 小型串行

  • 文本

  • 时间

  • 时间戳

  • timetz

  • uuid

  • varchar

  • varcharN—varchar(n)

  • xid

  • xml

  • ~--忽略元组中剩下的所有属性

    对我们来说,所有这些text都是类型字符可变的(255),但varcharN对我们不起作用,所以经过其他测试,我们最终将其更改为text

    对我们来说,timestamp是带时区的时间戳类型,但timetz对我们不起作用,所以在其他测试之后,我们最终将其更改为timestamp,并选择丢失时区数据。

    这种变化非常适合这张桌子。

    其他表格要简单得多:

    pg_filedump -D int,date,int,text 38183 | grep COPY > restored_table2.txt

  1. 因为我们得到的只是";生的";我们必须将数据重新格式化为CSV格式。因此,我们制作了一个从pg_filedump -D输出到CSV格式的python程序。

  2. 我们将每个CSV插入PostgreSQL(在再次创建每个空表之后):

    COPY scheme."table2"(id_comentari,id_observacio,text,data,id_usuari,text_old) 
    FROM '<path>/table2.csv' DELIMITER '|' CSV HEADER;
    

我希望这能帮助其他人:)

这是注定的。如果没有pg_xlog和(特别是)pg_clog中的信息,您就无法取回信息。

一个知识渊博的取证专家可能能够挽救你的一些数据,但这不是一个简单的过程。

相关内容

  • 没有找到相关文章

最新更新