从旧的完整转储恢复 PostgreSQL-9.6 数据库 and/or 一个最新的基本目录和其他获救的文件
Restore a PostgreSQL-9.6 database from an old complete dump and/or a up-to-date just base directory and other rescued files
我正在尝试 restore/rescue 我拥有的一些数据库:
我在PGDATA/base
(/var/lib/postgresql/9.6/main/base/
)中有所有最近的文件,但我没有完整的/var/lib/postgresql/9.6/main/
我在新安装的 PostgreSQL-9.6 中恢复了旧备份(并没有太大不同)转储中的所有文件。
我有很多从硬盘驱动器(来自 ddrescue
)拯救的文件,我有数千个没有名字的文件(有一个“#”,然后是一个数字,在 lost+found 目录中),因此,例如:
- 我有
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
读取这些文件
and/or 试图用这些名称文件命名它们(以
00000001000000000000000A
按日期并将它们放入新的 pg_xlog
目录,我看到系统文件命名它们,可能是?)。另外我发现最后一个有硬盘崩溃的日期,所以我有最后一个。
我从硬盘(已损坏)中抢救出来的PGDATA/base
目录包含目录1
、12406
、12407
和37972
,其中有很多里面的文件。我检查 pg_filedump -fi
我的更新数据是否存储在目录 37972
.
中的文件中
相同(但旧)的数据存储在还原转储中目录 PGDATA/base/16387
中的文件中。
我尝试直接将文件从一个文件复制到另一个文件,并在旧数据库上混合更新的数据,但它不起作用。解决权限错误后,我可以通过这种方式进入 "Frankenstein" 数据库:
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
文件是 "Frankenstein" 的一部分而不是好的文件(因为我还没有找到它,不是那个名字),所以我尝试:复制另一个首先看起来很相似,然后用 dd
为该文件生成 8192 个零,在这两种情况下我都会得到相同的错误(如果文件不存在则得到 DETAIL: Could not open file "pg_subtrans/0002": No such file or directory.
)。无论如何,我不知道那个文件应该是什么。您认为我可以从其他文件中获取该数据吗?或者我可以使用某种工具找到丢失的文件吗?所以 pg_filedump
显示那个目录 pg_subtrans/0000
.
中的另一个文件是空的
额外说明: 我发现了这个有用的博客 post,它讨论了使用 pg_filedump
、pg_class
从刚获救的文件中恢复文件,reindex system
和其他工具,但我很难理解如何使它适应我的具体和更简单的问题(我认为我的问题更容易,因为我有一个转储):https://www.commandprompt.com/blog/recovering_a_lost-and-found_database/
那是注定的。如果没有 pg_xlog
和(特别是)pg_clog
中的信息,您将无法取回信息。
知识渊博的取证专家也许能够挽救您的一些数据,但这不是一个简单的过程。
经过4个部分PGDATA/base/37972
目录,我们终于完全恢复了数据库:
检查并“greping”pg_filedump -fi
哪个文件对应
每个 table。为了更容易地“greping”,我们制作了一个脚本。
#!/bin/bash
for filename in ./*; do
echo "$filename"
pg_filedump -fi "$filename"|grep ""
done
注意:仅对小字符串有用。
执行伟大的工具pg_filedump -D
。 -D
是一个新选项(来自 postgresql-filedump
版本 ≥10),使用给定的逗号分隔类型列表解码元组。
因为我们创建了数据库,所以我们知道类型,我们“只”需要给出与 table 相关的类型的逗号分隔列表。我写“只是”是因为在某些情况下它可能有点复杂。我们的 table 之一需要这种命令:
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
大连载
布尔值
字符
charN -- 字符(n)
日期
浮动
float4
float8
整数
json
macaddr
姓名
oid
真实
连载
smallint
smallserial
文本
时间
时间戳
timetz
uuid
varchar
varcharN -- varchar(n)
xid
xml
~ -- 忽略元组中剩余的所有属性
所有这些 text
对我们来说都是类型字符 varying(255) 但 varcharN
对我们不起作用,所以在其他测试之后我们最终将其更改为 text
。
timestamp
对我们来说是类型 timestamp with time zone 但是 timetz
对我们不起作用,所以在其他测试之后我们最终将其更改为 timestamp
我们选择丢失时区数据。
此更改非常适合 table。
其他 table 更容易:
pg_filedump -D int,date,int,text 38183 | grep COPY > restored_table2.txt
因为我们得到的只是“原始”数据,所以我们必须重新格式化为 CSV 格式。所以我们为 format from pg_filedump -D
output to CSV.
制作了一个 python 程序
我们将每个 CSV 插入到 PostgreSQL(在再次创建每个空 table 之后):
COPY scheme."table2"(id_comentari,id_observacio,text,data,id_usuari,text_old)
FROM '<path>/table2.csv' DELIMITER '|' CSV HEADER;
我希望这对其他人有帮助:)
我正在尝试 restore/rescue 我拥有的一些数据库:
我在
PGDATA/base
(/var/lib/postgresql/9.6/main/base/
)中有所有最近的文件,但我没有完整的/var/lib/postgresql/9.6/main/
我在新安装的 PostgreSQL-9.6 中恢复了旧备份(并没有太大不同)转储中的所有文件。
我有很多从硬盘驱动器(来自
ddrescue
)拯救的文件,我有数千个没有名字的文件(有一个“#”,然后是一个数字,在 lost+found 目录中),因此,例如:- 我有
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
读取这些文件
and/or 试图用这些名称文件命名它们(以
00000001000000000000000A
按日期并将它们放入新的 pg_xlog
目录,我看到系统文件命名它们,可能是?)。另外我发现最后一个有硬盘崩溃的日期,所以我有最后一个。
我从硬盘(已损坏)中抢救出来的PGDATA/base
目录包含目录1
、12406
、12407
和37972
,其中有很多里面的文件。我检查 pg_filedump -fi
我的更新数据是否存储在目录 37972
.
相同(但旧)的数据存储在还原转储中目录 PGDATA/base/16387
中的文件中。
我尝试直接将文件从一个文件复制到另一个文件,并在旧数据库上混合更新的数据,但它不起作用。解决权限错误后,我可以通过这种方式进入 "Frankenstein" 数据库:
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
文件是 "Frankenstein" 的一部分而不是好的文件(因为我还没有找到它,不是那个名字),所以我尝试:复制另一个首先看起来很相似,然后用 dd
为该文件生成 8192 个零,在这两种情况下我都会得到相同的错误(如果文件不存在则得到 DETAIL: Could not open file "pg_subtrans/0002": No such file or directory.
)。无论如何,我不知道那个文件应该是什么。您认为我可以从其他文件中获取该数据吗?或者我可以使用某种工具找到丢失的文件吗?所以 pg_filedump
显示那个目录 pg_subtrans/0000
.
额外说明: 我发现了这个有用的博客 post,它讨论了使用 pg_filedump
、pg_class
从刚获救的文件中恢复文件,reindex system
和其他工具,但我很难理解如何使它适应我的具体和更简单的问题(我认为我的问题更容易,因为我有一个转储):https://www.commandprompt.com/blog/recovering_a_lost-and-found_database/
那是注定的。如果没有 pg_xlog
和(特别是)pg_clog
中的信息,您将无法取回信息。
知识渊博的取证专家也许能够挽救您的一些数据,但这不是一个简单的过程。
经过4个部分PGDATA/base/37972
目录,我们终于完全恢复了数据库:
检查并“greping”
pg_filedump -fi
哪个文件对应 每个 table。为了更容易地“greping”,我们制作了一个脚本。#!/bin/bash for filename in ./*; do echo "$filename" pg_filedump -fi "$filename"|grep "" done
注意:仅对小字符串有用。
执行伟大的工具
pg_filedump -D
。-D
是一个新选项(来自postgresql-filedump
版本 ≥10),使用给定的逗号分隔类型列表解码元组。因为我们创建了数据库,所以我们知道类型,我们“只”需要给出与 table 相关的类型的逗号分隔列表。我写“只是”是因为在某些情况下它可能有点复杂。我们的 table 之一需要这种命令:
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
大连载
布尔值
字符
charN -- 字符(n)
日期
浮动
float4
float8
整数
json
macaddr
姓名
oid
真实
连载
smallint
smallserial
文本
时间
时间戳
timetz
uuid
varchar
varcharN -- varchar(n)
xid
xml
~ -- 忽略元组中剩余的所有属性
所有这些
text
对我们来说都是类型字符 varying(255) 但varcharN
对我们不起作用,所以在其他测试之后我们最终将其更改为text
。timestamp
对我们来说是类型 timestamp with time zone 但是timetz
对我们不起作用,所以在其他测试之后我们最终将其更改为timestamp
我们选择丢失时区数据。此更改非常适合 table。
其他 table 更容易:
pg_filedump -D int,date,int,text 38183 | grep COPY > restored_table2.txt
因为我们得到的只是“原始”数据,所以我们必须重新格式化为 CSV 格式。所以我们为 format from
制作了一个 python 程序pg_filedump -D
output to CSV.我们将每个 CSV 插入到 PostgreSQL(在再次创建每个空 table 之后):
COPY scheme."table2"(id_comentari,id_observacio,text,data,id_usuari,text_old) FROM '<path>/table2.csv' DELIMITER '|' CSV HEADER;
我希望这对其他人有帮助:)