受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

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输出保存到某个地方非常重要。这有助于审计,也有助于诊断问题。(关于日志文件处理的更深入讨论,见Section 24.3。)

postgres还接受许多其他命令行选项。更多信息请见postgres参考页以及下面的Chapter 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系统上,可以把

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

    加入/etc/rc.d/rc.local/etc/rc.local,或者查看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功能的细节请见Section 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 域套接字与本地服务器通信时,你可能会看到下面的消息:

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并不表示服务器收到了你的连接请求并拒绝了它;那种情况会产生另一条消息,如Section 20.16所示。)其他错误消息,例如Connection timed out,可能表示更底层的问题,例如网络不通,或有防火墙阻塞了连接。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。