首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从旧的完整转储和/或最新的基本目录和其他获救文件中恢复PostgreSQL9.6数据库。

从旧的完整转储和/或最新的基本目录和其他获救文件中恢复PostgreSQL9.6数据库。
EN

Stack Overflow用户
提问于 2020-02-18 13:53:36
回答 2查看 1.1K关注 0票数 2

我正试图从我拥有的数据库中恢复/拯救一个数据库:

我有所有最近的文件在/var/lib/postgresql/9.6/main/

  • I (/var/lib/postgresql/9.6/main/base/)中,但是我没有完整的拥有从一个旧的备份(并且没有太大的不同)转储的所有文件,我在PostgreSQL-9.6.
  • I的新安装中恢复了很多文件,从硬盘(从ddrescue)获得了很多获救的文件,并且我得到了上千个没有名字的文件(有一个"#“,然后是一个数字,然后是在lost+found目录中),所以,例如:

代码语言:javascript
复制
- I have the `pg_class` file
- I have the `pg_clog` directory with `0000` file

编辑:

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

代码语言:javascript
复制
#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中的文件中。

我试图直接将文件从一个复制到另一个,将更新的数据混合到旧的数据库上,但是它不起作用。在解决权限错误后,我可以这样进入"Frankenstein“数据库:

代码语言:javascript
复制
 postgres@host:~$ postgres --single -P -D /var/lib/postgresql/9.6/main/ dbname

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

代码语言:javascript
复制
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文件是"Frankenstein“的一部分,而不是一个好的文件(因为我还没有找到它,而不是这个名字),所以我尝试了:先复制一个看起来类似的文件,然后用dd生成8192个零到该文件,在这两种情况下,我都会得到相同的错误(如果文件不存在,就会得到DETAIL: Could not open file "pg_subtrans/0002": No such file or directory.)。不管怎样,我不知道那个文件应该是什么。你认为我能从其他文件中得到数据吗?或者我能用一些工具找到丢失的文件吗?因此,pg_filedump为该目录pg_subtrans/0000中的另一个文件显示为空。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-23 11:37:21

最后,在完成以下4部分之后,我们基于PGDATA/base/37972目录完全恢复了数据库:

  1. 检查和对对应于每个表的文件的pg_filedump -fi进行“修饰”。为了“更好地”,我们做了一个剧本。

#!/bin/bash表示文件名在./*;执行回显"$filename“pg_filedump -fi”$filename“\grep "$1”已完成

注意:只对小字符串有用.

  1. 执行伟大的工具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

  • bigserial

  • bool

  • char

  • charN - char(n)

  • date

  • float

  • float4

  • float8

  • int

  • json

  • macaddr

  • name

  • oid

  • real

  • serial

  • smallint

  • smallserial

  • text

  • time

  • timestamp

  • timetz

  • uuid

  • varchar

varchar(n) -

  • varcharN

  • xid

  • xml

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

对于我们来说,所有这些text都是类型不同的字符(255),但是varcharN对我们不起作用,所以在其他测试之后,我们最终将它更改为text

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

这一更改非常适合此表。

其他表格则容易得多:

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

  1. 当我们获得“原始”数据时,我们必须重新格式化为CSV格式。所以我们为format from pg_filedump -D output to CSV.

编写了一个python程序

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

复制方案。“table2”(id_comentari、id_observacio、text、data、id_usuari、text_old)从'/table2.csv‘DELIMITER’\ CSV‘CSV标题;中复制。

我希望这会对其他人有所帮助:

票数 1
EN

Stack Overflow用户

发布于 2020-02-18 16:48:44

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

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

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60282485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档