PostgreSQL 查询创建目录

Posted

技术标签:

【中文标题】PostgreSQL 查询创建目录【英文标题】:PostgreSQL Query To Create A Directory 【发布时间】:2020-05-14 07:06:07 【问题描述】:

正在使用COPY 查询将文件写入目录:

Copy (SELECT * FROM animals) To '/var/lib/postgresql/data/backups/2020-01-01/animals.sql' With CSV DELIMITER ',';

但是如果目录2020-01-01 不存在,我们会得到错误

无法打开文件“/var/lib/postgresql/data/backups/2020-01-01/animals.sql”进行写入:没有这样的文件或目录

PostgeSQL 服务器在 Docker 容器中运行,卷映射为 /mnt/backups:/var/lib/postgresql/data/backups

Copy 查询是从 Docker 容器外部的 Node.js 应用发送的。

映射的主机目录/mnt/backups由Docker Compose创建,归root所有,因此发送COPY查询的Node.js应用由于权限不足而无法创建缺失的目录。

备份文件旨在从 Docker 容器中传输到 Docker 主机。

问题:如果目录不存在,是否可以使用 SQL 查询要求 PostgreSQL 11.2 创建目录?如果没有,您会建议如何创建目录?

在 Ubuntu 18.04 主机上使用 Node.js 12.14.1。在容器内使用 PostgreSQL 11.2,Docker 19.03.5

【问题讨论】:

这个文件需要在服务器中创建吗?是否可以选择直接在客户端计算机中创建它? @JimJones 可以直接在客户端机器(Ubuntu,也是Docker主机)中创建。如果在客户端计算机上创建,您是否认为它会明显变慢? 速度不会有差异。我会添加一个答案让你尝试一下 @JimJones 速度可能会有所不同,具体取决于网络和客户端的效率。使用to stdin,数据必须从服务器传输到客户端,然后再传输到磁盘。使用to 'file',它直接进入磁盘。 Postgres has its own backup and restore utilities。它们可能是比自己构建更好的选择。 【参考方案1】:

解决此问题的一种简单方法是将文件直接创建到客户端计算机中。使用COPY 中的STDOUT,您可以将查询输出重定向到客户端标准输出,您可以将其捕获并保存在文件中。例如,在客户端机器上使用psql

$ psql -U your_user -d your_db -c "COPY (SELECT * FROM animals) TO STDOUT WITH CSV DELIMITER ','" > file.csv 

创建一个输出目录以防它不存在:

$ mkdir -p /mnt/backups/2020-01/ && psql -U your_user -d your_db -c "COPY (SELECT * FROM animals) TO STDOUT WITH CSV DELIMITER ','" > /mnt/backups/2020-01/file.csv

附带说明:尽量避免将文件导出到数据库服务器。尽管这是可能的,但我认为这是一种不好的做法。这样做,您要么将文件写入 postgres 系统目录,要么授予 postgres 用户在其他地方写入的权限,这是您不应该感到舒服的事情。使用我提到的COPY 或遵循@Schwern 的建议将数据直接导出到客户端。祝你好运!

【讨论】:

刚试过你的命令,好像psql 没有为你创建目录。 /bin/sh: 1: cannot create /mnt/backups/2020-01/animals.sql: Directory nonexistent。是否有一个参数可以传递给psql,或者我们必须在运行psql 命令之前使用mkdir -p <dirname> 不,只是想知道是否可以在 1 个命令中巧妙地完成所有操作。 好吧,我会在psql 命令之前写mkdir -p your_directory_path。如果目录不存在,这将为您创建目录 @Nyxynyx 我刚刚在我的答案中添加了一行,可能是你想要的:) 祝你好运 谢谢。我还修改了psql 命令以使用psql .... | pigz -rsyncable > /mnt/backups/2020-01/animals.csv 的多线程压缩【参考方案2】:

Postgres has its own backup and restore utilities 这可能是比自己滚动更好的选择。

当与其中一种存档文件格式一起使用并与 pg_restore 结合使用时,pg_dump 提供了灵活的存档和传输机制。 pg_dump 可用于备份整个数据库,然后 pg_restore 可用于检查存档和/或选择要恢复的数据库的哪些部分。最灵活的输出文件格式是“自定义”格式(-Fc)和“目录”格式(-Fd)。它们允许选择和重新排序所有归档项目,支持并行恢复,并且默认压缩。 “目录”格式是唯一支持并行转储的格式。

一个简单的备份轮换脚本可能如下所示:

#!/bin/sh

table='animals'
url='postgres://username@host:port/database_name'
date=`date -Idate`
file="/path/to/your/backups/$date/$table.sql"

mkdir -p `dirname $file`

pg_dump $url -w -Fc --table=$table -f $file

为避免对数据库密码进行硬编码,-w 表示它不会提示输入密码,而是查找a password file。或者你可以使用任何many Postgres authentication options。

【讨论】:

以上是关于PostgreSQL 查询创建目录的主要内容,如果未能解决你的问题,请参考以下文章

以windows服务方式快速部署免安装版Postgres数据库

国际新闻|Citus 11 for Postgres 完全开源,可从任何节点查询

PostgreSQL最常用的函数-查询(最全)

postgres安装

使用 PostgreSQL 创建数据透视表

postgresql-10.12安装和部署