【问题标题】:PostgreSQL - dump each table into a different filePostgreSQL - 将每个表转储到不同的文件中
【发布时间】:2013-08-20 08:27:44
【问题描述】:

我需要从 PostgreSQL 数据库的多个表中提取 SQL 文件。到目前为止,这是我想出的:

pg_dump -t 'thr_*' -s dbName -U userName > /home/anik/psqlTest/db_dump.sql

但是,如您所见,所有以前缀 thr 开头的表都被导出到一个统一文件 (db_dump.sql)。我总共有近 90 个表可以从中提取 SQL,因此必须将数据存储到单独的文件中。

我该怎么做?提前致谢。

【问题讨论】:

  • 您需要解释为什么您需要 90 个不同的文件 - 导出到 MySQL,部分备份?如果您尝试进行备份/导出,那么 IMSoP 的答案将不能保证每个表的快照相同。
  • @RichardHuxton 好点,我没有想到非原子性。我想您可以改为从数据库创建一个“自定义”备份,然后使用 pg_restore 从中提取单个表。

标签: sql database postgresql postgresql-9.1 pg-dump


【解决方案1】:

从 PostgreSQL 9.1 版(2011 年 9 月)开始,在进行备份时可以使用 目录格式 输出

在 2 个版本/2 年后(PostgreSQL 9.3),--jobs/-j 使得并行备份每个对象变得更加高效

但我在您原来的问题中不明白的是,您使用了 -s 选项,它只转储对象定义(架构),而不是数据。

如果您想要数据,则不应使用 -s 而应使用 -a(仅数据)或不使用 schema+data 选项

因此,要备份目录 dbName_objects/ 上以 'th' 开头的数据库 dbName 的所有对象(表...),同时有 10 个并发作业/进程(增加服务器上的负载):

pg_dump -Fd -f dbName_objects -j 10 -t 'thr_*' -U userName dbName

(如果需要对象的数据或架构,也可以使用 -a/-s)

因此,该目录将填充一个 toc.dat(所有对象的目录)和一个压缩形式的每个对象的文件 (.dat.gz)

每个文件都以其对象编号命名,您可以使用以下 pg_restore 命令检索列表:

pg_restore --list -Fd dbName_objects/ | grep '表数据'

为了不压缩每个文件(在原始 SQL 中)

pg_dump --data-only --compress=0 --format=directory --file=dbName_objects --jobs=10 --table='thr_*' --username=userName --dbname=dbName

【讨论】:

  • 运行它只给我toc.dat,目录中没有其他文件...
  • 你到底运行了哪个命令?表在特定路径中吗?请提供更多上下文信息
  • 我尝试了这两个命令,但我对后者感兴趣,即没有压缩以获得普通 SQL 文件的命令。我没有使用table 参数,因为我想转储所有DB 对象--schema-only
  • 我想我找到了问题所在:--schema-only 不会生成多个文件,但会生成一个包含数据库定义的文件...
【解决方案2】:

如果您乐于对表列表进行硬编码,但只是希望每个表位于不同的文件中,则可以使用 shell 脚本循环多次运行 pg_dump 命令,分别替换表名循环时间:

for table in table1 table2 table3 etc;
do pg_dump -t $table -U userName dbName > /home/anik/psqlTest/db_dump_dir/$table.sql;
done;

编辑:这种方法可以扩展为通过 psql 运行查询并将结果输入循环而不是硬编码列表来动态获取表列表:

for table in $(psql -U userName -d dbName -t -c "Select table_name From information_schema.tables Where table_type='BASE TABLE' and table_name like 'thr_%'");
do pg_dump -t $table -U userName dbName > /home/anik/psqlTest/db_dump_dir/$table.sql;
done;

这里psql -t -c "SQL" 运行SQL 并输出没有页眉或页脚的结果;由于只选择了一列,$(command) 捕获的输出的每一行都会有一个表名,您的 shell 将一次循环遍历它们。

【讨论】:

  • 我将在表名参数中使用通配符。硬编码 90 个表名!到时候我就老了。 :)
  • @HasanIqbalAnik 或者,您可以从 shell 脚本中查询数据库以获取表列表,然后遍历列表。
  • @HasanIqbalAnik 我想你可能会这么说,这就是我在答案开头添加警告的原因。正如 Igor 建议的那样,我已经编辑了我的答案以首先在数据库中查询列表。
  • 警告:这种方法会将每个表存储在不同时间的状态中,因为脚本将花费时间进行循环。如果在备份期间数据库发生更改,这可能会导致状态不一致。所以请确保在备份过程中数据库没有被改变!
【解决方案3】:

(没有足够的声誉来评论正确的帖子) 我使用您的脚本进行了一些更正和一些修改以供我自己使用,可能对其他人有用:

#!/bin/bash

# Config:
DB=rezopilotdatabase
U=postgres
# tablename searchpattern, if you want all tables enter "":
P=""
# directory to dump files without trailing slash:
DIR=~/psql_db_dump_dir

mkdir -p $DIR
TABLES="$(psql -d $DB -U $U -t -c "SELECT table_name FROM 
information_schema.tables WHERE table_type='BASE TABLE' AND table_name 
LIKE '%$P%' ORDER BY table_name")"
for table in $TABLES; do
  echo backup $table ...
  pg_dump $DB -U $U -w -t $table > $DIR/$table.sql;
done;
echo done

(我想你忘了在 pg_dumb 命令中添加 $DB,我添加了 -w,对于自动化脚本,我猜最好不要有 psw 提示符,为此,我创建了一个 ~/. pgpass 文件,里面有我的密码 我还让用户知道要在 .pgpass 中获取哪个密码) 希望有一天这对某人有所帮助。

【讨论】:

  • 不错。您只需要在某处包含架构名称。
  • 我不得不做一些调整,但这个脚本效果很好。谢谢。
【解决方案4】:

此 bash 脚本将使用每个表的一个文件进行备份:

#!/bin/bash

# Config:
DB=dbName
U=userName
# tablename searchpattern, if you want all tables enter "":
P=""
# directory to dump files without trailing slash:
DIR=~/psql_db_dump_dir

mkdir -p $DIR
AUTH="-d $DB -U $U"
TABLES="$(psql $AUTH -t -c "SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_name LIKE '%$P%' ORDER BY table_name")"
for table in $TABLES; do
  echo backup $table ...
  pg_dump $AUTH -t $table > $DIR/$table.sql;
done;
echo done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 2020-12-07
    相关资源
    最近更新 更多