2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2

18.3. 启动数据库服务器 #

在任何人能够访问数据库之前,您必须启动数据库服务器。数据库服务器程序名为 postgres

如果您使用的是预打包的 PostgreSQL 版本,它几乎肯定包含了按照您的操作系统约定将服务器作为后台任务运行的机制。使用包的基础设施来启动服务器会比您自己弄清楚如何做到这一点要省事得多。有关详细信息,请参阅包级别的文档。

手动启动服务器的简陋方式就是直接调用 postgres,并使用 -D 选项指定数据目录的位置,例如:

$ postgres -D /usr/local/pgsql/data

这将使服务器在前台运行。这必须在登录到 PostgreSQL 用户帐户时进行。如果不使用 -D,服务器将尝试使用由环境变量 PGDATA 指定的数据目录。如果该变量也未提供,则会失败。

通常最好在后台启动 postgres。为此,请使用常规的 Unix shell 语法:

$ postgres -D /usr/local/pgsql/data >logfile 2>&1 &

如上所示,将服务器的 stdoutstderr 输出存储在某个位置很重要。这将有助于审计和诊断问题。(有关日志文件处理的更详细讨论,请参见 第 24.3 节。)

此外,postgres 程序还接受许多其他命令行选项。有关更多信息,请参见 postgres 参考页和下面的 第 19 章

这种 shell 语法很快就会变得繁琐。因此,提供了包装程序 pg_ctl 来简化一些任务。例如:

pg_ctl start -l logfile

将会在后台启动服务器并将输出放入指定的日志文件中。-D 选项在这里的含义与 postgres 相同。pg_ctl 也能够停止服务器。

通常,您希望在计算机启动时启动数据库服务器。 自启动脚本是特定于操作系统的。在 PostgreSQLcontrib/start-scripts 目录中分发了一些示例脚本。安装其中一个需要 root 权限。

不同的系统在启动时的守护进程启动方式上具有不同的约定。许多系统都有 /etc/rc.local/etc/rc.d/rc.local 文件。其他系统使用 init.drc.d 目录。无论您做什么,服务器都必须由 PostgreSQL 用户帐户运行,而不是由 root 或任何其他用户运行。因此,您可能应该使用 su postgres -c '...' 来构建您的命令。例如:

su postgres -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog'

以下是一些特定于操作系统的建议。(在每种情况下,请务必在显示通用值的地方使用正确的安装目录和用户名。)

  • 对于 FreeBSD,请查看 PostgreSQL 源代码分发中的 contrib/start-scripts/freebsd 文件。

  • OpenBSD 上,将以下行添加到 /etc/rc.local 文件中:

    if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postgres ]; then
        su -l postgres -c '/usr/local/pgsql/bin/pg_ctl start -s -l /var/postgresql/log -D /usr/local/pgsql/data'
        echo -n ' postgresql'
    fi
    
  • Linux 系统上,将以下命令之一添加到 /etc/rc.d/rc.local/etc/rc.local 中,或者查看 PostgreSQL 源代码分发中的 contrib/start-scripts/linux 文件:

    /usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data
    

    或者查看 PostgreSQL 源代码分发中的 contrib/start-scripts/linux 文件。

    在使用 systemd 时,您可以使用以下服务单元文件(例如,在 /etc/systemd/system/postgresql.service):

    [Unit]
    Description=PostgreSQL database server
    Documentation=man:postgres(1)
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=notify
    User=postgres
    ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
    ExecReload=/bin/kill -HUP $MAINPID
    KillMode=mixed
    KillSignal=SIGINT
    TimeoutSec=infinity
    
    [Install]
    WantedBy=multi-user.target
    

    使用 Type=notify 要求服务器二进制文件是使用 configure --with-systemd 构建的。

    请仔细考虑超时设置。截至本文撰写之时,systemd 的默认超时时间为 90 秒,并且会在进程在此时限内未能报告就绪状态时将其终止。但是,执行崩溃恢复的 PostgreSQL 服务器在启动时可能需要更长时间才能就绪。建议的 infinity 值会禁用超时逻辑。

  • NetBSD 上,根据您的偏好使用 FreeBSDLinux 启动脚本。

  • Solaris 上,创建一个名为 /etc/init.d/postgresql 的文件,其中包含以下行:

    su - postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data"
    

    然后,在 /etc/rc3.d 中创建一个指向它的符号链接,命名为 S99postgresql

当服务器运行时,它的PID存储在数据目录中的 postmaster.pid 文件中。这用于防止多个服务器实例在同一个数据目录中运行,并且还可以用于关闭服务器。

18.3.1. 服务器启动失败 #

服务器可能由于多种常见原因而无法启动。检查服务器的日志文件,或者(不重定向标准输出或标准错误)手动启动服务器,看看会出现什么错误消息。下面我们将更详细地解释一些最常见的错误消息。

LOG:  could not bind IPv4 address "127.0.0.1": Address already in use
HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
FATAL:  could not create any TCP/IP sockets

这通常表示其字面意思:您尝试在已有一个服务器正在运行的端口上启动另一个服务器。但是,如果内核错误消息不是 Address already in use 或其变体,则可能存在其他问题。例如,尝试在保留的端口号上启动服务器可能会出现类似以下内容的提示:

$ postgres -p 666
LOG:  could not bind IPv4 address "127.0.0.1": Permission denied
HINT:  Is another postmaster already running on port 666? If not, wait a few seconds and retry.
FATAL:  could not create any TCP/IP sockets

类似如下的消息:

FATAL:  could not create shared memory segment: Invalid argument
DETAIL:  Failed system call was shmget(key=5440001, size=4011376640, 03600).

可能表示您的内核对共享内存大小的限制小于 PostgreSQL 试图创建的工作区(本例中为 4011376640 字节)。这仅在您将 shared_memory_type 设置为 sysv 时才可能发生。在这种情况下,您可以尝试使用小于正常数量的缓冲区 (shared_buffers) 来启动服务器,或者重新配置您的内核以增加允许的共享内存大小。当尝试在同一台机器上启动多个服务器时,如果它们请求的总空间超过了内核限制,您也可能会看到此消息。

类似如下的错误:

FATAL:  could not create semaphores: No space left on device
DETAIL:  Failed system call was semget(5440126, 17, 03600).

表示您已用完磁盘空间。它表示您的内核对 System V 信号量数量的限制小于 PostgreSQL 想要创建的数量。与上面一样,您可能可以通过使用减少的连接数 (max_connections) 来启动服务器来解决问题,但最终您将需要增加内核限制。

有关配置 System V 的详细信息IPC设施,请参见 第 18.4.1 节

18.3.2. 客户端连接问题 #

尽管客户端可能遇到的错误条件多种多样且取决于应用程序,但其中一些可能与服务器的启动方式直接相关。除下面显示的条件外的情况应在相应的客户端应用程序文档中说明。

psql: error: connection to server at "server.joe.com" (123.123.123.123), port 5432 failed: Connection refused
        Is the server running on that host and accepting TCP/IP connections?

这是通用的“找不到可以通信的服务器”失败。当尝试 TCP/IP 通信时,它看起来像上面这样。一个常见的错误是忘记配置 listen_addresses 以便服务器接受远程 TCP 连接。

或者,当尝试与本地服务器进行 Unix-domain 套接字通信时,您可能会收到此错误:

psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such file or directory
        Is the server running locally and accepting connections on that socket?

如果服务器确实正在运行,请检查客户端的套接字路径(此处为 /tmp)是否与服务器的 unix_socket_directories 设置一致。

连接失败消息始终会显示服务器地址或套接字路径名称,这有助于验证客户端是否正在尝试连接到正确的位置。如果实际上没有服务器在那里监听,内核错误消息通常是 Connection refusedNo such file or directory,如所示。(重要的是要认识到,在这种情况下,Connection refused 表示服务器收到了您的连接请求并拒绝了它。这种情况会产生不同的消息,如 第 20.16 节 所示。)其他错误消息,例如 Connection timed out,可能表示更根本的问题,例如网络连接丢失或防火墙阻止了连接。

提交更正

如果您在文档中看到任何不正确之处、与您在使用特定功能时的体验不符或需要进一步澄清的内容,请使用 此表格 报告文档问题。