19.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 &
如上所示,将服务器的stdout和stderr输出存储在某处非常重要。它将有助于进行审计和诊断问题。(有关日志文件处理的更全面讨论,请参见第 25.3 节。)
postgres
程序还采用许多其他命令行选项。有关更多信息,请参见postgres参考页和下面的第 20 章。
此 shell 语法很快会变得乏味。因此,包装程序pg_ctl用于简化某些任务。例如
pg_ctl start -l logfile
将在后台启动服务器,并将输出放入指定日志文件。-D
选项在此处的含义与postgres
相同。pg_ctl
还能够停止服务器。
通常,您希望在计算机启动时启动数据库服务器。自动启动脚本是特定于操作系统的。在contrib/start-scripts
目录中,有一些与PostgreSQL一起分发的示例脚本。安装其中一个脚本需要 root 权限。
不同的系统在启动时启动守护进程有不同的约定。许多系统都有一个文件/etc/rc.local
或/etc/rc.d/rc.local
。其他系统使用init.d
或rc.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/guide/log -D /usr/local/pgsql/data' echo -n ' postgresql' fi
/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
的建议值禁用超时逻辑。在 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
中。这用于防止多个服务器实例在同一数据目录中运行,还可以用于关闭服务器。
19.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
这通常意味着它暗示的意思:你尝试在已经运行服务器的同一端口上启动另一个服务器。但是,如果内核错误消息不是地址已在使用中
或它的某个变体,则可能存在其他问题。例如,尝试在保留端口号上启动服务器可能会出现类似以下内容
$ 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 VIPC设施的详细信息,请参阅第 19.4.1 节。
19.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 通信时,它看起来像上面那样。一个常见的错误是忘记配置服务器以允许 TCP/IP 连接。
或者,在尝试与本地服务器进行 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 refused
或No such file or directory
,如图所示。(重要的是要认识到,在此上下文中Connection refused
不表示服务器收到了您的连接请求并拒绝了它。这种情况会产生不同的消息,如第 21.15 节中所示。)其他错误消息,例如Connection timed out
,可能表明存在更基本的问题,例如缺乏网络连接或防火墙阻止了连接。