搜索

7.4. 使用 PostgreSQL

download PDF

PostgreSQL 服务器是一个基于 SQL 语言的开源、健壮且高度可扩展的数据库服务器。PostgreSQL 服务器提供了一个对象关系型数据库系统,其可以管理大量的数据集和大量的并发用户。因此,PostgreSQL 服务器可在集群中用来管理大量数据。

PostgreSQL 服务器包括用于确保数据完整性、构建容错环境和应用程序的功能。使用 PostgreSQL 服务器,您可以使用您自己的数据类型、自定义功能或来自不同编程语言的代码来扩展数据库,而无需重新编译数据库。

了解如何在 RHEL 系统上安装和配置 PostgreSQL,如何备份 PostgreSQL 数据,以及如何从早期的 PostgreSQL 版本迁移。

7.4.1. 安装 PostgreSQL

在 RHEL 8 中,PostgreSQL 服务器在多个版本中提供,每个版本都由单独的流提供:

  • PostgreSQL 10 - 默认流
  • PostgreSQL 9.6
  • PostgreSQL 12 - 从 RHEL 8.1.1 开始提供
  • PostgreSQL 13 - 从 RHEL 8.4 开始提供
  • PostgreSQL 15 - 从 RHEL 8.8 开始提供
  • PostgreSQL 16 - 从 RHEL 8.10 开始可用
注意

按照设计,无法并行安装同一模块的多个版本(stream)。因此,您必须从 postgresql 模块中只选择一个可用流。您可以在容器中使用不同版本的 PostgreSQL 数据库服务器,请参阅 在容器中运行多个 PostgreSQL 版本

要安装 PostgreSQL,请使用以下流程:

流程

  1. 通过从 postgresql 模块中选择一个流(版本),并指定 server 配置文件来安装 PostgreSQL 服务器软件包。例如:

    # yum module install postgresql:16/server

    postgres 超级用户会自动创建。

  2. 初始化数据库集群:

    # postgresql-setup --initdb

    红帽建议将数据存储在默认的 /var/lib/pgsql/data 目录中。

  3. 启动 postgresql 服务:

    # systemctl start postgresql.service
  4. 启用 postgresql 服务,以便在引导时启动:

    # systemctl enable postgresql.service

有关使用模块流的详情,请参阅 安装、管理和删除用户空间组件

重要

如果要从 RHEL 8 中的早期 postgresql 流升级,请按照 切换到更新的流迁移到 PostgreSQL 的 RHEL 8 版本 中描述的两个步骤进行。

7.4.1.1. 在容器中运行多个 PostgreSQL 版本

要在同一主机上运行不同版本的 PostgreSQL,请在容器中运行它们,因为您无法并行安装同一模块的多个版本(streams)。

此流程包括 PostgreSQL 13PostgreSQL 15 作为示例,但您可以使用 Red Hat Ecosystem Catalog 中提供的任何 PostgreSQL 容器版本。

先决条件

  • container-tools 模块已安装。

流程

  1. 使用您的红帽客户门户网站帐户向 registry.redhat.io registry 进行身份验证:

    # podman login registry.redhat.io

    如果您已登录到容器 registry,请跳过这一步。

  2. 在容器中运行 PostgreSQL 13

    $ podman run -d --name <container_name> -e POSTGRESQL_USER=<user_name> -e POSTGRESQL_PASSWORD=<password> -e POSTGRESQL_DATABASE=<database_name> -p <host_port_1>:5432 rhel8/postgresql-13

    有关使用此容器镜像的更多信息,请参阅 红帽生态系统目录

  3. 在容器中运行 PostgreSQL 15

    $ podman run -d --name <container_name> -e POSTGRESQL_USER=<user_name> -e POSTGRESQL_PASSWORD=<password> -e POSTGRESQL_DATABASE=<database_name> -p <host_port_2>:5432 rhel8/postgresql-15

    有关使用此容器镜像的更多信息,请参阅 红帽生态系统目录

  4. 在容器中运行 PostgreSQL 16

    $ podman run -d --name <container_name> -e POSTGRESQL_USER=<user_name> -e POSTGRESQL_PASSWORD=<password> -e POSTGRESQL_DATABASE=<database_name> -p <host_port_3>:5432 rhel8/postgresql-16

    有关使用此容器镜像的更多信息,请参阅 红帽生态系统目录

    注意

    两个数据库服务器的容器名称和主机端口必须有所不同。

  5. 要确保客户端可以访问网络中的数据库服务器,请在防火墙中打开主机端口:

    # firewall-cmd --permanent --add-port={<host_port_1>/tcp,<host_port_2>/tcp,...}
    # firewall-cmd --reload

验证

  1. 显示正在运行的容器信息:

    $ podman ps
  2. 连接到数据库服务器,并以 root 用户身份登录:

    # psql -u postgres -p -h localhost -P <host_port> --protocol tcp

7.4.2. 创建 PostgreSQL 用户

PostgreSQL 用户为以下类型:

  • postgres UNIX 系统用户 - 应该仅用于运行 PostgreSQL 服务器和客户端应用程序,如 pg_dump。不要将 postgres 系统用户用于 PostgreSQL 管理的任何交互式工作,如数据库创建和用户管理。
  • 数据库超级用户 - 默认的 postgres PostgreSQL 超级用户与 postgres 系统用户无关。您可以在 pg_hba.conf 文件中限制 postgres 超级用户的权限,否则没有其他权限限制。您也可以创建其他数据库超级用户。
  • 具有特定数据库访问权限的角色:

    • 数据库用户 - 默认具有登录权限
    • 一组用户 - 启用整个组的管理权限

角色可以拥有数据库对象(如表和函数),并且可以使用 SQL 命令将对象特权分配给其他角色。

标准数据库管理特权包括 SELECTINSERTUPDATEDELETETRUNCATEREFERENCESTRIGGERCREATECONNECTTEMPORARYEXECUTEUSAGE

角色属性是特殊的特权,如 LOGINSUPERUSERCREATEDBCREATEROLE

重要

红帽建议以不是超级用户的角色身份执行大部分任务。常见的做法是创建一个具有 CREATEDBCREATEROLE 特权的角色,并将此角色用于所有数据库和角色的日常管理。

先决条件

  • PostgreSQL 服务器已安装。
  • 数据库集群已初始化。

流程

  • 要创建用户,请为用户设置密码,并为该用户分配 CREATEROLECREATEDB 权限:

    postgres=# CREATE USER mydbuser WITH PASSWORD 'mypasswd' CREATEROLE CREATEDB;

    mydbuser 替换为 username,将mypasswd 替换为用户的密码。

例 7.1. 初始化、创建和连接到 PostgreSQL 数据库

本例演示了如何初始化 PostgreSQL 数据库,创建具有例行数据库管理特权的数据库用户,以及如何创建可通过具有管理特权的任何系统帐户访问的数据库帐户。

  1. 安装 PosgreSQL 服务器:

    # yum module install postgresql:13/server
  2. 初始化数据库集群:

    # postgresql-setup --initdb
    * Initializing database in '/var/lib/pgsql/data'
    * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log
  3. 将密码哈希算法设为 scram-sha-256

    1. /var/lib/pgsql/data/postgresql.conf 文件中,更改以下行:

      #password_encryption = md5              # md5 or scram-sha-256

      改为:

      password_encryption = scram-sha-256
    2. /var/lib/pgsql/data/pg_hba.conf 文件中,更改 IPv4 本地连接的以下行:

      host    all             all             127.0.0.1/32            ident

      改为:

      host    all             all             127.0.0.1/32            scram-sha-256
  4. 启动 postgresql 服务:

    # systemctl start postgresql.service
  5. 以名为 postgres 的系统用户身份登录:

    # su - postgres
  6. 启动 PostgreSQL 交互终端:

    $ psql
    psql (13.7)
    Type "help" for help.
    
    postgres=#
  7. 可选:获取有关当前数据库连接的信息:

    postgres=# \conninfo
    You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
  8. 创建名为 mydbuser 的用户,为 mydbuser 设置密码,并为 mydbuser 分配 CREATEROLECREATEDB 权限:

    postgres=# CREATE USER mydbuser WITH PASSWORD 'mypasswd' CREATEROLE CREATEDB;
    CREATE ROLE

    mydbuser 用户现在可以执行日常数据库管理操作:创建数据库并管理用户索引。

  9. 使用 \q meta 命令从交互终端退出:

    postgres=# \q
  10. 退出 postgres 用户会话:

    $ logout
  11. mydbuser 用户身份登录到 PostgreSQL 终端,指定主机名,并连接到默认的 postgres 数据库,该数据库是在初始化过程中创建的:

    # psql -U mydbuser -h 127.0.0.1 -d postgres
    Password for user mydbuser:
    Type the password.
    psql (13.7)
    Type "help" for help.
    
    postgres=>
  12. 创建名为 mydatabase 的数据库:

    postgres=> CREATE DATABASE mydatabase;
    CREATE DATABASE
    postgres=>
  13. 退出会话:

    postgres=# \q
  14. mydbuser 用户身份连接到 mydatabase:

    # psql -U mydbuser -h 127.0.0.1 -d mydatabase
    Password for user mydbuser:
    psql (13.7)
    Type "help" for help.
    mydatabase=>
  15. 可选:获取有关当前数据库连接的信息:

    mydatabase=> \conninfo
    You are connected to database "mydatabase" as user "mydbuser" on host "127.0.0.1" at port "5432".

7.4.3. 配置 PostgreSQL

PostgreSQL 数据库中,所有数据和配置文件都存储在一个名为database cluster的目录中。红帽建议将所有数据(包括配置文件)存储在默认的 /var/lib/pgsql/data/ 目录中。

PostgreSQL 配置由以下文件组成:

  • PostgreSQL.conf - 用于设置数据库集群参数。
  • PostgreSQL.auto.conf - 包含与 postgresql.conf 类似的基本 PostgreSQL 设置。但是这个文件由服务器控制。它由 ALTER SYSTEM 查询来编辑,无法手动编辑。
  • pg_ident.conf - 用于将来自外部身份验证机制的用户身份映射到 PostgreSQL 用户身份。
  • pg_hba.conf - 用于为 PostgreSQL 数据库配置客户端身份验证。

要修改 PostgreSQL 配置,请使用以下流程:

流程

  1. 编辑相应的配置文件,如 /var/lib/pgsql/data/postgresql.conf
  2. 重启 postgresql 服务,以使修改生效:

    # systemctl restart postgresql.service

例 7.2. 配置 PostgreSQL 数据库集群参数

本例展示了 /var/lib/pgsql/data/postgresql.conf 文件中数据库集群参数的基本设置。

# This is a comment
log_connections = yes
log_destination = 'syslog'
search_path = '"$user", public'
shared_buffers = 128MB
password_encryption = scram-sha-256

例 7.3. 在 PostgreSQL 中设置客户端身份验证

本例演示了如何在 /var/lib/pgsql/data/pg_hba.conf 文件中设置客户端身份验证。

# TYPE    DATABASE       USER        ADDRESS              METHOD
local     all            all                              trust
host      postgres       all         192.168.93.0/24      ident
host      all            all         .example.com         scram-sha-256

7.4.4. 在 PostgreSQL 服务器上配置 TLS 加密

默认情况下,PostgreSQL 使用未加密的连接。如需更多安全连接,您可以在 PostgreSQL 服务器上启用传输层安全(TLS)支持,并配置客户端,以建立加密连接。

先决条件

  • PostgreSQL 服务器已安装。
  • 数据库集群已初始化。

流程

  1. 安装 OpenSSL 库:

    # yum install openssl
  2. 生成 TLS 证书和密钥:

    # openssl req -new -x509 -days 365 -nodes -text -out server.crt \
      -keyout server.key -subj "/CN=dbhost.yourdomain.com"

    dbhost.yourdomain.com 替换为您的数据库主机和域名。

  3. 将签名的证书和私钥复制到数据库服务器上所需的位置:

    # cp server.{key,crt} /var/lib/pgsql/data/.
  4. 将签名证书和私钥的所有者和组所有权改为 postgres 用户:

    # chown postgres:postgres /var/lib/pgsql/data/server.{key,crt}
  5. 限制私钥的权限,使其只对所有者可读:

    # chmod 0400 /var/lib/pgsql/data/server.key
  6. 通过更改 /var/lib/pgsql/data/postgresql.conf 文件中的以下行,将密码哈希算法设为 scram-sha-256

    #password_encryption = md5              # md5 or scram-sha-256

    改为:

    password_encryption = scram-sha-256
  7. 通过更改 /var/lib/pgsql/data/postgresql.conf 文件中的以下行,将 PostgreSQL 配置为使用 SSL/TLS:

    #ssl = off

    改为:

    ssl=on
  8. 通过更改 /var/lib/pgsql/data/pg_hba.conf 文件中 IPv4 本地连接的以下行,将对所有数据库的访问限制为只接受使用 TLS 的客户端连接:

    host		all		all		127.0.0.1/32		ident

    改为:

    hostssl 	all		all		127.0.0.1/32		scram-sha-256

    另外,您可以通过添加以下新行来限制对单个数据库和用户的访问:

    hostssl	mydatabase	mydbuser	127.0.0.1/32		scram-sha-256

    mydatabase 替换为数据库名称,将 mydbuser 替换为 username。

  9. 通过重启 postgresql 服务来使更改有效:

    # systemctl restart postgresql.service

验证

  • 要手动验证连接是否是加密的:

    1. mydbuser 用户身份连接到 PostgreSQL 数据库,指定主机名和数据库名称:

      $ psql -U mydbuser -h 127.0.0.1 -d mydatabase
      Password for user mydbuser:

      mydatabase 替换为数据库名称,将 mydbuser 替换为 username。

    2. 获取有关当前数据库连接的信息:

      mydbuser=> \conninfo
      You are connected to database "mydatabase" as user "mydbuser" on host "127.0.0.1" at port "5432".
      SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
  • 您可以编写一个简单的应用程序,其验证到 PostgreSQL 的连接是否是加密的。本例演示了使用 C 编写的使用 libpq 客户端库(由 libpq-devel 软件包提供)的应用程序:

    #include <stdio.h>
    #include <stdlib.h>
    #include <libpq-fe.h>
    
    int main(int argc, char* argv[])
    {
    //Create connection
    PGconn* connection = PQconnectdb("hostaddr=127.0.0.1 password=mypassword port=5432 dbname=mydatabase user=mydbuser");
    
    if (PQstatus(connection) ==CONNECTION_BAD)
        {
        printf("Connection error\n");
        PQfinish(connection);
        return -1; //Execution of the program will stop here
        }
        printf("Connection ok\n");
        //Verify TLS
        if (PQsslInUse(connection)){
         printf("TLS in use\n");
         printf("%s\n", PQsslAttribute(connection,"protocol"));
        }
        //End connection
        PQfinish(connection);
        printf("Disconnected\n");
        return 0;
    }

    mypassword 替换为密码,将 mydatabase 替换为数据库名称,将 mydbuser 替换为 username。

    注意

    您必须使用 -lpq 选项为编译加载 pq 库。例如,要使用 GCC 编译器编译应用程序:

    $ gcc source_file.c -lpq -o myapplication

    其中 source_file.c 包含上面的示例代码,myapplication 是用于验证安全的 PostgreSQL 连接的应用程序的名称。

例 7.4. 初始化、创建,并使用 TLS 加密连接到 PostgreSQL 数据库

本例演示了如何初始化 PostgreSQL 数据库,创建数据库用户和数据库,以及如何使用安全连接连接到数据库。

  1. 安装 PosgreSQL 服务器:

    # yum module install postgresql:13/server
  2. 初始化数据库集群:

    # postgresql-setup --initdb
    * Initializing database in '/var/lib/pgsql/data'
    * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log
  3. 安装 OpenSSL 库:

    # yum install openssl
  4. 生成 TLS 证书和密钥:

    # openssl req -new -x509 -days 365 -nodes -text -out server.crt \
      -keyout server.key -subj "/CN=dbhost.yourdomain.com"

    dbhost.yourdomain.com 替换为您的数据库主机和域名。

  5. 将签名的证书和私钥复制到数据库服务器上所需的位置:

    # cp server.{key,crt} /var/lib/pgsql/data/.
  6. 将签名证书和私钥的所有者和组所有权改为 postgres 用户:

    # chown postgres:postgres /var/lib/pgsql/data/server.{key,crt}
  7. 限制私钥的权限,使其只对所有者可读:

    # chmod 0400 /var/lib/pgsql/data/server.key
  8. 将密码哈希算法设为 scram-sha-256。在 /var/lib/pgsql/data/postgresql.conf 文件中,更改以下行:

    #password_encryption = md5              # md5 or scram-sha-256

    改为:

    password_encryption = scram-sha-256
  9. 将 PostgreSQL 配置为使用 SSL/TLS。在 /var/lib/pgsql/data/postgresql.conf 文件中,更改以下行:

    #ssl = off

    改为:

    ssl=on
  10. 启动 postgresql 服务:

    # systemctl start postgresql.service
  11. 以名为 postgres 的系统用户身份登录:

    # su - postgres
  12. postgres 用户身份启动 PostgreSQL 交互终端:

    $ psql -U postgres
    psql (13.7)
    Type "help" for help.
    
    postgres=#
  13. 创建名为 mydbuser 的用户,并为 mydbuser 设置密码:

    postgres=# CREATE USER mydbuser WITH PASSWORD 'mypasswd';
    CREATE ROLE
    postgres=#
  14. 创建名为 mydatabase 的数据库:

    postgres=# CREATE DATABASE mydatabase;
    CREATE DATABASE
    postgres=#
  15. 将 all 权限赋予 mydbuser 用户:

    postgres=# GRANT ALL PRIVILEGES ON DATABASE mydatabase TO mydbuser;
    GRANT
    postgres=#
  16. 退出交互终端:

    postgres=# \q
  17. 退出 postgres 用户会话:

    $ logout
  18. 通过更改 /var/lib/pgsql/data/pg_hba.conf 文件中 IPv4 本地连接的以下行,将对所有数据库的访问限制为只接受使用 TLS 的客户端连接:

    host		all		all		127.0.0.1/32		ident

    改为:

    hostssl 	all		all		127.0.0.1/32		scram-sha-256
  19. 通过重启 postgresql 服务来使更改有效:

    # systemctl restart postgresql.service
  20. mydbuser 用户身份连接到 PostgreSQL 数据库,指定主机名和数据库名称:

    $ psql -U mydbuser -h 127.0.0.1 -d mydatabase
    Password for user mydbuser:
    psql (13.7)
    SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
    Type "help" for help.
    
    mydatabase=>

7.4.5. 备份 PostgreSQL 数据

要备份 PostgreSQL 数据,请使用以下方法之一:

SQL 转储
请参阅 使用 SQL 转储备份
文件系统级别备份
请参阅 文件系统级备份
持续归档
请参阅 持续归档

7.4.5.1. 使用 SQL 转储备份 PostgreSQL 数据

SQL 转储方法基于使用 SQL 命令生成转储文件。当转储上传回数据库服务器时,它会按与转储时相同的状态重新创建数据库。

以下 PostgreSQL 客户端应用程序为 SQL 转储提供了保证:

  • pg_dump 转储单个数据库,而无需有关角色或表空间的集群范围的信息
  • pg_dumpall 转储给定集群中的每个数据库,并保留集群范围的数据,如角色和表空间定义。

默认情况下,pg_dumppg_dumpall 命令将它的们结果写入标准输出。要将转储保存到文件中,请将输出重定向到 SQL 文件。生成的 SQL 文件可以是文本格式,也可以是允许并行且可以更详细地控制对象恢复的其他格式。

您可以在任何可访问数据库的远程主机中执行 SQL 转储。

7.4.5.1.1. SQL 转储的优点和缺陷

与其它 PostgreSQL 备份方法相比,SQL 转储具有以下优点:

  • SQL 转储是唯一的、不针对特定服务器版本的 PostgreSQL 备份方法。pg_dump 工具的输出可以重新加载到 PostgreSQL 的后续版本中,这不适用于文件系统级备份或持续归档。
  • SQL 转储是将数据库传输到不同计算机架构(比如从 32 位服务器传输到 64 位服务器)的唯一方法。
  • SQL 转储提供内部一致的转储。转储表示在pg_dump 开始运行时的数据库快照。
  • pg_dump 程序不会阻止数据库中的其他操作。

SQL 转储的一个缺点是,与文件系统级备份相比,它需要更长的时间。

7.4.5.1.2. 使用 pg_dump 执行 SQL 转储

要转储一个没有集群范围信息的单个数据库,请使用 pg_dump 工具。

先决条件

  • 您必须对要转储的所有表具有读的权限。若要转储整个数据库,您必须以 postgres 超级用户或具有数据库管理员特权的用户身份运行命令。

流程

  • 转储没有集群范围信息的数据库:

    $ pg_dump dbname > dumpfile

要指定 pg_dump 会联系哪个数据库服务器,请使用以下命令行选项:

  • -h 选项用来定义主机 。

    默认主机要么是本地主机,要么是 PGHOST 环境变量所指定的主机。

  • -p 选项用来定义端口 。

    默认端口是由 PGPORT 环境变量或编译后的默认值指明的。

7.4.5.1.3. 使用 pg_dumpall 执行 SQL 转储

要转储给定数据库集群中的每个数据库,并保留集群范围的数据,请使用 pg_dumpall 工具。

先决条件

  • 您必须以 postgres 超级用户或具有数据库管理员特权的用户身份运行命令。

流程

  • 转储数据库集群中的所有数据库,并保留集群范围的数据:

    $ pg_dumpall > dumpfile

要指定pg_dumpall与哪个数据库服务器联系,请使用以下命令行选项:

  • -h 选项用来定义主机 。

    默认主机要么是本地主机,要么是 PGHOST 环境变量所指定的主机。

  • -p 选项用来定义端口 。

    默认端口是由 PGPORT 环境变量或编译后的默认值指明的。

  • -l 选项用来定义默认数据库。

    这个选项使您能够选择一个与初始化过程中自动创建的 postgres 数据库不同的默认数据库。

7.4.5.1.4. 恢复使用 pg_dump 转储的数据库

要从使用 pg_dump 工具转储的 SQL 转储恢复数据库,请按照以下流程。

先决条件

  • 您必须以 postgres 超级用户或具有数据库管理员特权的用户身份运行命令。

流程

  1. 创建新数据库:

    $ createdb dbname
  2. 验证在转储数据库中拥有对象或被赋予了对象权限的所有用户是否已存在。如果这样的用户不存在,恢复将无法重新创建具有原始所有权和权限的对象。
  3. 运行 psql 工具来恢复 pg_dump 程序创建的文本文件转储:

    $ psql dbname < dumpfile

    其中 dumpfilepg_dump 命令的输出。要恢复非文本文件转储,请使用 pg_restore 工具:

    $ pg_restore non-plain-text-file
7.4.5.1.5. 恢复使用 pg_dumpall 转储的数据库

要从使用 pg_dumpall 工具转储的数据库集群中恢复数据,请按照以下步骤。

先决条件

  • 您必须以 postgres 超级用户或具有数据库管理员特权的用户身份运行命令。

流程

  1. 确保在转储数据库中拥有对象或已被赋予了对象权限的所有用户已存在。如果这样的用户不存在,恢复将无法重新创建具有原始所有权和权限的对象。
  2. 运行 psql 工具来恢复由 pg_dumpall 工具创建的文本文件转储:

    $ psql < dumpfile

    其中 dumpfilepg_dumpall 命令的输出。

7.4.5.1.6. 在另一服务器上执行数据库的 SQL 转储

将数据库从一台服务器直接转储到另一台服务器是可能的,因为 pg_dumppsql 可以写入管道并从管道读取。

流程

  • 要从一个服务器到另一个服务器转储数据库,请运行:

    $ pg_dump -h host1 dbname | psql -h host2 dbname
7.4.5.1.7. 在恢复过程中处理 SQL 错误

默认情况下,如果出现 SQL 错误,psql 会继续执行,从而导致数据库只部分恢复。

要修改默认行为,在恢复转储时使用以下任一方法:

先决条件

  • 您必须以 postgres 超级用户或具有数据库管理员特权的用户身份运行命令。

流程

  • 请设置 ON_ERROR_STOP 变量,使 psql 在发生 SQL 错误时退出,且有一个为 3 的退出状态码:

    $ psql --set ON_ERROR_STOP=on dbname < dumpfile
  • 指定整个转储作为一个事务来恢复,以便要么全部完成,要么全部取消。

    • 使用 psql 工具恢复文本文件转储时:

      $ psql -1
    • 使用 pg_restore 工具恢复非文本文件转储时:

      $ pg_restore -e

      请注意,在使用这个方法时,即使一个小的错误也可以取消已经运行了很长时间的恢复操作。

7.4.5.1.8. 其它资源

7.4.5.2. 使用文件系统级别备份来备份 PostgreSQL 数据

要创建文件系统级备份,请将 PostgreSQL 数据库文件复制到另一个位置。例如,您可以使用以下任一方法:

  • 使用 tar 工具创建归档文件。
  • 使用 rsync 工具将文件复制到其它位置。
  • 创建数据目录的一致快照。
7.4.5.2.1. 文件系统备份的优点和限制

与其它 PostgreSQL 备份方法相比,文件系统级备份有以下优点:

  • 文件系统级备份通常比 SQL 转储快。

与其它 PostgreSQL 备份方法相比,文件系统级备份有以下限制:

  • 当您想从 RHEL 7 升级到 RHEL 8 ,并将数据迁移到升级的系统时,这个备份方法不适用。文件系统级别备份特定于架构和 RHEL 主版本。如果升级不成功,您可以恢复 RHEL 7 系统上的数据,但您无法恢复 RHEL 8 系统上的数据。
  • 在备份和恢复数据前,数据库服务器必须关闭。
  • 无法备份和恢复某些单独的文件或表。备份文件系统只适用于整个数据库集群的完整备份和恢复。
7.4.5.2.2. 执行文件系统级备份

要执行文件系统级备份,请使用以下流程。

流程

  1. 选择数据库集群的位置,并初始化该集群:

    # postgresql-setup --initdb
  2. 停止 postgresql 服务:

    # systemctl stop postgresql.service
  3. 使用任意方法创建文件系统备份,如 tar 归档:

    $ tar -cf backup.tar /var/lib/pgsql/data
  4. 启动 postgresql 服务:

    # systemctl start postgresql.service

7.4.5.3. 通过持续存档来备份 PostgreSQL 数据

7.4.5.3.1. 持续归档介绍

PostgreSQL 将对数据库的数据文件所做的每项修改记录到预写日志(WAL)文件中,该文件位于集群数据目录的 pg_wal/ 子目录中。此日志主要用于崩溃恢复。崩溃后,可用上次检查点以后所记录的日志条目将数据库恢复到一致。

持续归档方法也称为在线备份,以在运行的服务器上执行的基础备份或文件系统级备份的形式,将 WAL 文件与数据库集群的副本结合起来。

如果需要进行数据库恢复,您可以从数据库集群的副本恢复数据库,然后从备份的 WAL 文件中重新执行日志,使系统恢复到当前状态。

使用持续归档方法时,您必须保持所有归档的 WAL 文件的连续顺序,这些文件至少可扩展到上一次基础备份的开始时间。因此,基本备份的理想频率取决于:

  • 归档 WAL 文件的存储卷。
  • 需要恢复时数据恢复的最可能持续时间。自上次备份以来的很长一段时间,系统重新运行了更多 WAL 段,因此恢复需要更长的时间。
注意

您不能将 pg_dumppg_dumpall SQL 转储用作持续归档备份解决方案的一部分。SQL 转储生成逻辑备份,但所包含的信息不足以供WAL重新执行。

要使用持续归档方法执行数据库备份和恢复,请按照以下说明:

  1. 设置并测试归档 WAL 文件的流程 - 请参阅 WAL 归档
  2. 执行一个基础备份 - 请参阅 基础备份

要恢复您的数据,请遵循 使用持续归档恢复数据库 中的说明。

7.4.5.3.2. 持续归档的优点和缺陷

与其它 PostgreSQL 备份方法相比,持续归档具有以下优势:

  • 使用持续备份方法时,可以使用不完全一致的基础备份,因为备份中的任何内部不一致都可以被重新执行日志所修正。因此,您可以在运行的 PostgreSQL 服务器上执行基础备份。
  • 不需要文件系统快照; tar 或类似的归档工具就足够了。
  • 持续备份可以通过继续归档 WAL 文件来实现,因为日志重播的 WAL 文件序列可能会无限期地延长。这对大型数据库尤其重要。
  • 持续备份支持点恢复。不需要将 WAL 条目重新显示到结尾。可在任何时间点停止重新执行,并且数据库可以恢复到执行基础备份以后的任何状态。
  • 如果已经加载了相同的基础备份文件的另一台机器可以连续使用WAL文件系列,那么可以在任何时候用数据库几乎当前的副本来恢复其它机器。

与其他 PostgreSQL 备份方法相比,持续归档有以下缺点:

  • 持续备份方法只支持恢复整个数据库集群,而不是子集。
  • 持续备份需要广泛的归档存储。
7.4.5.3.3. 设置 WAL 归档

运行的 PostgreSQL 服务器会生成一系列预写日志(WAL)记录。服务器物理上将该序列分成 WAL 段文件,这些文件被指定了数字名称,以反映它们在 WAL 序列中的位置。如果不进行 WAL 归档,段文件将被重新使用,并被重命名为更高的段号。

在归档 WAL 数据时,在重用段文件之前,都会捕获每一个段文件的内容,并将其保存在一个新的位置。您有多个保存内容的选项,例如其他机器上的 NFS 挂载目录、磁带驱动器或 CD。

请注意,WAL 记录不包括对配置文件的修改。

要启用 WAL 归档,请使用以下流程:

流程

  1. /var/lib/pgsql/data/postgresql.conf 文件中:

    1. wal_level 配置参数设置为 replica 或更高的值。
    2. archive_mode 参数设置为 on
    3. archive_command 配置参数中指定 shell 命令。您可以使用 cp 命令、其它命令或 shell 脚本。
  2. 重启 postgresql 服务以使修改生效:

    # systemctl restart postgresql.service
  3. 测试您的归档命令,并确保它不会覆盖现有的文件,如果失败,它将返回一个非零退出状态。
  4. 要保护您的数据,请确保将段文件归档到不具有组或全局读权限的目录中。
注意

归档命令只对已完成的 WAL 段执行。生成小 WAL 流量的服务器在交易完成和其归档存储中的安全记录之间可能会有很长时间的延迟。要限制未归档数据可保留多久,您可以:

  • 设置 archive_timeout 参数,来强制服务器以给定频率切换到新的 WAL 段文件。
  • 使用 pg_switch_wal 参数强制段切换,以确保交易在完成后立即归档。

例 7.5. 用于归档 WAL 段的 shell 命令

本例显示了您可以在 archive_command 配置参数中设置的简单 shell 命令。

以下命令将完成的段文件复制到所需位置:

archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

其中 %p 参数替换为归档文件的相对路径,%f 参数替换为文件名。

此命令将可归档的 WAL 段复制到 /mnt/server/archivedir/ 目录中。替换 %p%f 参数后,执行的命令如下所示:

test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065

对每个归档的新文件都会生成类似的命令。

其它资源

7.4.5.3.4. 进行基础备份

您可以通过多种方法创建基础备份:执行基础备份的最简单方法是在运行的 PostgreSQL 服务器上使用 pg_basebackup 工具。

基础备份进程会创建一个备份历史记录文件,该文件存储在 WAL 归档区,并以基础备份所需的第一个 WAL 段文件来命名。

备份历史记录文件是一个小文本文件,其包含开始和结束时间,以及备份的 WAL 段。如果您使用标签字符串来标识关联的转储文件,那么您可以使用备份历史记录文件来确定要恢复哪个转储文件。

注意

请考虑保留多个备份集,以确保您可以恢复数据。

要执行基础备份,请使用以下流程:

先决条件

  • 您必须以 postgres 超级用户身份、具有数据库管理员特权的用户身份或至少具有 REPLICATION 权限的其他用户身份来运行命令。
  • 您必须保留在基础备份期间和之后生成的所有 WAL 段文件。

流程

  1. 使用 pg_basebackup 工具执行基础备份。

    • 将基础备份创建为单个的文件(纯格式):

      $ pg_basebackup -D backup_directory -Fp

      使用您选择的备份位置替换 backup_directory

      如果您在与服务器相同的主机上使用表空间并执行基础备份,那么也必须使用 --tablespace-mapping 选项,否则当试图将备份写入到同一位置时,备份将失败。

    • 将基础备份创建为一个 tar 归档(tar 和压缩格式):

      $ pg_basebackup -D backup_directory -Ft -z

      使用您选择的备份位置替换 backup_directory

      要恢复此数据,您必须手动提取正确位置中的文件。

  2. 基础备份进程完成后,将备份历史记录文件中指定的数据库集群副本和备份过程中使用的 WAL 段文件进行安全归档。
  3. 删除比基础备份中使用的 WAL 段文件数值更低的WAL段,因为这些比基础备份旧,并且不再需要进行恢复。

要指定serverpg_basebackup将与哪个数据库联系,请使用以下命令行选项:

  • -h 选项用来定义主机的。

    默认主机要么是本地主机,要么是 PGHOST 环境变量所指定的主机。

  • -p 选项用来定义端口。

    默认端口是由 PGPORT 环境变量或编译后的默认值指明的。

7.4.5.3.5. 使用持续归档备份来恢复数据库

要使用持续备份来恢复数据库,请使用以下流程:

流程

  1. 停止服务器:

    # systemctl stop postgresql.service
  2. 将必要的数据复制到临时位置。

    最好复制整个集群数据目录和任何表空间。请注意,这需要系统上有足够的可用空间来保存现有数据库的两个副本。

    如果您没有足够的空间,就保存集群的pg_wal 目录的内容,其中可能包含系统关闭前没有归档的日志。

  3. 删除集群数据目录下的所有现有文件和子目录,并在您要使用的任何表空间的根目录下删除。
  4. 从您的基础备份恢复数据库文件。

    确保:

    • 恢复的文件具有正确的所有权(数据库系统用户,而不是 root)。
    • 恢复的文件具有正确的权限。
    • pg_tblspc/ 子目录中的符号链接被正确恢复。
  5. 删除 pg_wal/ 子目录中的任何文件。

    这些文件源自基础备份,因此已过时。如果您没有归档 pg_wal/,请重新创建它,并使其具有正确的权限。

  6. 将你在步骤 2 中保存的任何未归档的 WAL 段文件复制到 pg_wal/ 中。
  7. 在集群数据目录中创建 restore.conf 恢复命令文件,并在 restore_command 配置参数中指定 shell 命令。您可以使用 cp 命令、其它命令或 shell 脚本。例如:

    restore_command = 'cp /mnt/server/archivedir/%f "%p"'
  8. 启动服务器:

    # systemctl start postgresql.service

    服务器将进入恢复模式,并继续读取所需的存档 WAL 文件。

    如果恢复因为外部错误而终止,那么可以重启服务器,它将继续进行恢复。恢复过程完成后,服务器将 restore.conf 重命名为 restore.done。这可以防止服务器在启动正常的数据库操作后意外重新进入恢复模式。

  9. 检查数据库的内容,以验证数据库是否已恢复到所需的状态。

    如果数据库尚未恢复到所需状态,请返回到第 1 步。如果数据库已恢复到所需的状态,那么通过恢复 pg_hba.conf 文件中的客户端身份验证配置来允许用户进行连接。

有关使用持续备份恢复的更多信息,请参阅 PostgreSQL 文档

7.4.5.3.6. 其它资源

7.4.6. 迁移到 PostgreSQL 的 RHEL 8 版本

Red Hat Enterprise Linux 7 包含 PostgreSQL 9.2 作为 PostgreSQL 服务器的默认版本。另外,PostgreSQL 的几个版本也作为 RHEL 7 的软件集合提供。

Red Hat Enterprise Linux 8 提供 PostgreSQL 10 作为默认的 postgresql 流、PostgreSQL 9.6PostgreSQL 12PostgreSQL 13PostgreSQL 15PostgreSQL 16

Red Hat Enterprise Linux 上的 PostgreSQL 用户可为数据库文件使用两个迁移路径:

快速升级方法比转储和恢复过程要快。然而,在某些情况下,快速升级无法正常工作,您只能使用转储和恢复过程。这种情况包括:

  • 跨架构升级
  • 使用 plpythonplpython2 扩展的系统。请注意,RHEL 8 AppStream 存储库只包含 postgresql-plpython3 软件包,而不包含 postgresql-plpython2 软件包。
  • PostgreSQL 的 Red Hat Software Collections 版本迁移不支持快速升级。

迁移到更新版本的 PostgreSQL 的先决条件是备份所有 PostgreSQL 数据库。

转储和恢复过程需要转储数据库并执行SQL文件备份,建议使用快速升级方法。

在迁移到 PostgreSQL 的后续版本前,请参阅您要迁移的 PostgreSQL 版本 的上游兼容性备注,以及您要迁移的版本和目标版本之间的所有跳过的 PostgreSQL 版本。

7.4.6.1. PostgreSQL 15 和 PostgreSQL 16 之间的显著区别

PostgreSQL 16 引入了以下显著变化。

postmasters 二进制文件不再可用

PostgreSQL 不再与 postmaster 二进制文件一起发布。使用提供的 systemd 单元文件(systemctl start postgres 命令)启动 postgresql 服务器的用户不受这个更改的影响。如果您之前通过 postmaster 二进制文件直接启动了 postgresql 服务器,则您现在必须使用 postgres 二进制文件。

文档不再被打包

PostgreSQL 不再提供软件包中的 PDF 格式文档。改为使用 在线文档

7.4.6.2. PostgreSQL 13 和 PostgreSQL 15 之间的显著区别

PostgreSQL 15 引入了以下向后不兼容的更改:

public 模式的默认权限

PostgreSQL 15 中修改了 public 模式的默认权限。新创建的用户需要使用 GRANT ALL ON SCHEMA public TO myuser; 命令明确授予权限。

以下示例在 PostgreSQL 13 及更早版本中正常工作:

postgres=# CREATE USER mydbuser;
postgres=# \c postgres mydbuser
postgres=$ CREATE TABLE mytable (id int);

以下示例在 PostgreSQL 15 及更高版本中工作:

postgres=# CREATE USER mydbuser;
postgres=# GRANT ALL ON SCHEMA public TO mydbuser;
postgres=# \c postgres mydbuser
postgres=$ CREATE TABLE mytable (id int);
注意

确保在 pg_hba.conf 文件中正确配置了 mydbuser 访问。如需更多信息,请参阅 创建 PostgreSQL 用户

Pipeline 模式下不再支持 PQsendQuery()

PostgreSQL 15 开始,pipeline 模式下不再支持 libpq PQsendQuery() 函数。修改受影响的应用程序,以使用 PQsendQueryParams() 函数。

7.4.6.3. 使用 pg_upgrade 工具快速升级

在快速升级过程中,必须将二进制数据文件复制到 /var/lib/pgsql/data/ 目录中,并使用 pg_upgrade 工具。

您可以使用此方法迁移数据:

  • 从 RHEL 7 系统的 PostgreSQL 9.2 迁移到 RHEL 8 的 PostgreSQL 10
  • 从 RHEL 8 的 PostgreSQL 10 版本到 PostgreSQL 12的 RHEL 版本
  • 从 RHEL 8 的 PostgreSQL 12 版本到 PostgreSQL 13的 RHEL 版本
  • 从 RHEL 版本的 PostgreSQL 13PostgreSQL 15的 RHEL 版本
  • 从 RHEL 版本的 PostgreSQL 15PostgreSQL 16的 RHEL 版本

如果要从 RHEL 8 上的早期 postgresql 流升级,请按照 切换到更新流 中描述的步骤,然后迁移 PostgreSQL 数据。

若要在 RHEL 上的其他 PostgreSQL 版本组合之间迁移,以及从 PostgreSQL 的红帽软件集合版本迁移到 RHEL,请使用 Dump 和恢复升级

以下流程描述了使用快速升级方法从 PostgreSQL 9.2 的 RHEL 7 系统版本迁移到 PostgreSQL 的 RHEL 8 版本。

先决条件

  • 在执行升级前,请备份存储在 PostgreSQL 数据库中的所有数据。默认情况下,所有数据都存储在 RHEL 7 和 RHEL 8 系统上的 /var/lib/pgsql/data/ 目录中。

流程

  1. 在 RHEL 8 系统上,启用您要迁移的流(版本):

    # yum module enable postgresql:stream

    使用所选 PostgreSQL 服务器版本替换 stream

    如果使用默认流(提供了 PostgreSQL 10),则可以省略这一步。

  2. 在 RHEL 8 系统上,安装 postgresql-serverpostgresql-upgrade 软件包:

    # yum install postgresql-server postgresql-upgrade

    另外,如果您在 RHEL 7 上使用了任何 PostgreSQL 服务器模块,那么也可以在 RHEL 8 系统上安装该模块的两个版本,分别针对 PostgreSQL 9.2 (作为 postgresql-upgrade 软件包安装)和 PostgreSQL 的目标版本(作为 postgresql-server 软件包安装)进行编译。如果您需要编译第三方PostgreSQL服务器模块,请根据postgresql-develpostgresql-upgrade-devel软件包来构建它。

  3. 检查以下项:

    • 基本配置:在 RHEL 8 系统上,检查您的服务器是否使用默认的 /var/lib/pgsql/data 目录,是否正确初始化并启用了数据库。此外,数据文件必须存储在 /usr/lib/systemd/system/postgresql.service 文件中提及的相同路径。
    • PostgreSQL 服务器:您的系统可以运行多个 PostgreSQL 服务器。确保所有这些服务器的数据目录都是独立处理的。
    • PostgreSQL 服务器模块:确保您在 RHEL 7 中使用的 PostgreSQL 服务器模块也安装在 RHEL 8 系统中。请注意,插件安装在 /usr/lib64/pgsql/ 目录中(或者在 32 位系统的 /usr/lib/pgsql/ 目录中)。
  4. 确保 postgresql 服务在复制数据时未在源和目标系统上运行。

    # systemctl stop postgresql.service
  5. 将数据库文件从源位置复制到 RHEL 8 系统上的 /var/lib/pgsql/data/ 目录中。
  6. PostgreSQL 用户身份运行以下命令来执行升级过程:

    # postgresql-setup --upgrade

    这会在后台启动 pg_upgrade 进程。

    在出现故障时,postgresql-setup 会提供一条说明性的错误消息。

  7. 将之前的配置从 /var/lib/pgsql/data-old 复制到新集群。

    请注意,快速升级不会在较新的数据栈中重用之前的配置,配置是从零开始生成的。如果要手动组合旧配置和新配置,请使用数据目录中的 *.conf 文件。

  8. 启动新的 PostgreSQL 服务器:

    # systemctl start postgresql.service
  9. 分析新的数据库集群。

    • 对于 PostgreSQL 13 或更早版本:

      su postgres -c '~/analyze_new_cluster.sh'
    • 对于 PostgreSQL 15 或更高版本:

      su postgres -c 'vacuumdb --all --analyze-in-stages'
      注意

      您可能需要使用 ALTER COLLATION 名称 REFRESH VERSION,请查看 上游文档 了解详细信息。

  10. 如果您希望新 PostgreSQL 服务器在引导时自动启动,请运行:

    # systemctl enable postgresql.service

7.4.6.4. 转储和恢复升级

使用转储和恢复升级时,您必须将所有的数据库内容转储到 SQL 文件转储文件中。

请注意,转储和恢复升级比快速升级方法慢,并且可能在生成的 SQL 文件中需要一些手动修复。

您可以使用此方法迁移以下数据:

  • Red Hat Enterprise Linux 7 系统的 PostgreSQL 9.2
  • 早期 Red Hat Enterprise Linux 8 版本的 PostgreSQL
  • 与来自 Red Hat Software Collections 相同或更早版本的 PostgreSQL

    • PostgreSQL 9.2 (不再支持)
    • PostgreSQL 9.4 (不再支持)
    • PostgreSQL 9.6 (不再支持)
    • PostgreSQL 10
    • PostgreSQL 12
    • PostgreSQL 13

在 RHEL 7 和 RHEL 8 系统上,PostgreSQL 数据默认存储在 /var/lib/pgsql/data/ 目录中。对于 PostgreSQL 的红帽软件集合版本,默认数据目录为 /var/opt/rh/collection_name/lib/pgsql/data/postgresql92 除外,它使用 /opt/rh/postgresql92/root/var/lib/pgsql/data/ 目录)。

如果要从 RHEL 8 上的早期 postgresql 流升级,请按照 切换到更新流 中描述的步骤,然后迁移 PostgreSQL 数据。

要执行转储和恢复升级,请将用户改为 root

以下流程描述了从 PostgreSQL 9.2 的 RHEL 7 系统版本迁移到 PostgreSQL 的 RHEL 8 版本。

流程

  1. 在 RHEL 7 系统中,启动 PostgreSQL 9.2 服务器:

    # systemctl start postgresql.service
  2. 在 RHEL 7 系统上,将所有数据库内容转储到 pgdump_file.sql 文件中:

    su - postgres -c "pg_dumpall > ~/pgdump_file.sql"
  3. 验证数据库是否已正确转储:

    su - postgres -c 'less "$HOME/pgdump_file.sql"'

    结果显示的转储的 sql 文件的路径为:/var/lib/pgsql/pgdump_file.sql

  4. 在 RHEL 8 系统中,启用您要迁移的流(版本):

    # yum module enable postgresql:stream

    使用所选 PostgreSQL 服务器版本替换 stream

    如果使用默认流(提供了 PostgreSQL 10),则可以省略这一步。

  5. 在 RHEL 8 系统上,安装 postgresql-server 软件包:

    # yum install postgresql-server

    另外,如果您在 RHEL 7 中使用了任何 PostgreSQL 服务器模块,也需要在 RHEL 8 系统中安装它们。如果您需要编译第三方 PostgreSQL 服务器模块,请根据 postgresql-devel 软件包进行构建。

  6. 在 RHEL 8 系统中,初始化新 PostgreSQL 服务器的数据目录:

    # postgresql-setup --initdb
  7. 在 RHEL 8 系统上,将 pgdump_file.sql 复制到 PostgreSQL 主目录中,并检查该文件是否被正确复制:

    su - postgres -c 'test -e "$HOME/pgdump_file.sql" && echo exists'
  8. 复制 RHEL 7 系统中的配置文件:

    su - postgres -c 'ls -1 $PGDATA/*.conf'

    要复制的配置文件包括:

    • /var/lib/pgsql/data/pg_hba.conf
    • /var/lib/pgsql/data/pg_ident.conf
    • /var/lib/pgsql/data/postgresql.conf
  9. 在 RHEL 8 系统中,启动新的 PostgreSQL 服务器:

    # systemctl start postgresql.service
  10. 在 RHEL 8 系统中,从转储的 sql 文件中导入数据:

    su - postgres -c 'psql -f ~/pgdump_file.sql postgres'
注意

当从 PostgreSQL 的红帽软件集合版本升级时,请将命令调整为包含 scl enable collection_name。例如,要转储 rh-postgresql96 软件集合中的数据,请使用以下命令:

su - postgres -c 'scl enable rh-postgresql96 "pg_dumpall > ~/pgdump_file.sql"'
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.