1. 云栖社区>
  2. 博客列表>
  3. 正文

PostgreSQL服务器管理:服务器设置和操作

琴瑟 2017-08-21 12:52:24 浏览444 评论0

java PostgreSQL 服务器 postgres 加密 数据库 配置 操作系统 Server

摘要: 本章讨论如何设置和运行数据库服务器,以及它与操作系统的交互。 本文档为PostgreSQL 9.6.0文档,本转载已得到原译者彭煜玮授权。

本文档为PostgreSQL 9.6.0文档,本转载已得到原译者彭煜玮授权。

1. PostgreSQL用户账户

和对外部世界可访问的任何服务器守护进程一样,我们也建议在一个独立的用户账户下运行PostgreSQL。这个用户账户应该只拥有被该服务器管理的数据,并且应该不能被其他守护进程共享(例如,使用用户nobody是一个坏主意)。我们不建议把可执行文件安装为属于这个用户,因为妥协系统可能接着修改它们自己的二进制文件。

要在你的系统中增加一个 Unix 用户账户,查看一个命令useradd或adduser。通常会用postgres(本书中也假定用这个账户),但是你可以使用另一个名称。

2. 创建一个数据库集簇

在你能做任何事情之前,你必须在磁盘上初始化一个数据库存储区域。我们称之为一个数据库集簇(SQL标准使用的术语是目录集簇)。一个数据库集簇是被一个运行数据库服务器的单一实例所管理的一个数据库的集合。在初始化之后,一个数据库集簇将包含一个名为postgres的数据库,它表示被功能、用户和第三方应用所使用的默认数据库。数据库服务器本身并不要求postgres数据库存在。另一个在初始化过程中为每一个集簇创建的数据库被称为template1。顾名思义,它将被用于创建后续数据库的模板;它不应该被用于实际工作(在集簇内创建新数据库的更多信息请见Chapter 22)。

在文件系统术语中,一个数据库集簇是一个单一目录,所有数据都将被存储在其中。我们称它为数据目录或数据区域。在哪里存储你的数据完全由你选择。没有默认的位置,不过/usr/local/pgsql/data或/var/lib/pgsql/data位置比较流行。要初始化一个数据库集簇,使用和PostgreSQL一起安装的命令initdb。你的数据库集簇的文件系统位置由-D选项指定,例如:


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

注意你必须在使用PostgreSQL用户账户(如前一节所示)登录后执行这个命令。

Tip: 作为-D选项的一种替换方案,你可以设置环境变量PGDATA。

另一种替代方案是,你可以通过pg_ctl程序来运行initdb:


$ pg_ctl -D /usr/local/pgsql/data initdb

如果你使用pg_ctl来启停服务器(见Section 18.3),这种方法可能更直观,以为这样pg_ctl将是你用来管理数据库服务器实例的唯一命令。

如果你指定的目录还不存在,initdb将尝试创建它。当然,如果initdb没有在父目录中的写权限,这将会失败。通常推荐让PostgreSQL用户拥有数据目录及其父目录,这样就不存在上面的问题了。如果想要的父目录也不存在,你将需要先创建它,如果父父目录不可写则使用 root 特权。因此,该过程可能像这样:


root# mkdir /usr/local/pgsql
root# chown postgres /usr/local/pgsql
root# su postgres
postgres$ initdb -D /usr/local/pgsql/data

如果数据目录存在并且已经包含文件,initdb将拒绝运行。这可以避免无意中覆盖一个已有的安装。

因为数据目录包含所有存储在数据库里的数据,所以最重要的是保护这个目录不受未授权的访问。因此,initdb会回收禁止除PostgreSQL用户之外所有用户的访问权限。

不过,虽然目录的内容是安全的,但默认的客户端认证设置允许任意本地用户连接到数据库甚至成为数据库超级用户。如果你不信任其他本地用户, 我们建议你使用initdb的-W、--pwprompt或--pwfile选项之一给数据库超级用户赋予一个口令。还可以指定-A md5或-A password,这样就不会使用默认的trust 身份认证。或者在执行initdb之后、第一次启动服务器之前修改生成的pg_hba.conf文件(另外一些可行的方法包括peer认证或者用文件系统权限限制连接。)。

initdb同时也为数据库集簇初始化默认区域。 通常,它将只是使用环境中的区域设置并且把它们应用于被初始化的数据库。 可以为数据库指定一个不同的区域;特定数据库集簇中使用的默认排序顺序是通过initdb设置的, 虽然你可以创建使用不同排序顺序的新数据库,但在 initdb 创建的模板数据库中使用的顺序不能更改(除非删除并重建它们)。使用非C或POSIX的区域还会对性能造成影响。因此,第一次就正确地选择很重要。

initdb还为数据库集簇设置默认的字符集编码。通常字符集编码应该选择与区域设置匹配。

非C以及非POSIX区域对于字符集排序依赖于操作系统的排序规则库。这控制着索引中存储的键的排序。为此,通过快照恢复、二进制流复制、更换不同的操作系统或者升级操作系统都不能把一个集簇切换到一种不兼容的排序规则库版本。

2.1. 二级文件系统的使用

很多安装会在文件系统(卷)而不是机器的"根"卷上创建它们的数据库集簇。如果你选择这样做,我们不建议尝试使用二级卷的顶层目录(挂载点)作为数据目录。最好的做法是在PostgreSQL用户拥有的挂载点目录中创建一个目录,然后在其中创建数据目录。这可以避免权限问题,特别是对于pg_upgrade这类操作,并且它也能在二级卷被断线后确保干净的失败。

2.2. 网络文件系统的使用

许多安装会在网络文件系统上创建它们的数据库集簇。有时直接通过NFS, 或通过内部使用NFS的网络附加存储设备(NAS)完成。 PostgreSQL不对 NFS文件系统做特殊处理,即它假定NFS的行为和本地连接的设备完全一样。如果客户端或者服务器NFS没有提供标准的文件系统语义,这将导致可靠性问题 (参阅http://www.time-travellers.org/shane/papers/NFS_considered_harmful.html )。 具体来说,延迟(异步)写入到NFS服务器可以导致数据损坏问题。 如果可能的话,把NFS文件系统挂载为同步(无高速缓存)可以避免这种灾难。还有,我们不推荐软挂载的NFS文件系统。

存储区域网络(SAN)通常使用非NFS的通讯协议,并且可能或者不可能遭受这类灾难。建议咨询供应商的文档来了解数据一致性保证。PostgreSQL无法做到比它所使用的文件系统更可靠。

3. 启动数据库服务器

在任何人可以访问数据库前,你必须启动数据库服务器。 数据库服务器程序是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输出存储到某个地方是非常重要的。这将对审计目的和诊断问题有所帮助。

postgres还接受其它一些命令行选项。

这些 shell 语法很容易让人觉得无聊。因此我们提供了包装器程序pg_ctl以简化一些任务。例如:


pg_ctl start -l logfile

将在后台启动服务器并且把输出放到指定的日志文件中。-D选项和postgres中的一样。pg_ctl还可以用于停止服务器。

通常,你会希望在计算机启动的时候启动数据库服务器。自动启动脚本是操作系统相关的。PostgreSQL在contrib/start-scripts目录中提供了几种。安装将需要 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/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)

[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=0

[Install]
WantedBy=multi-user.target

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

要仔细地考虑超时设置。在写作这份文档时,systemd的默认超时时长是 90 秒,并且将会杀死没有在这段时间内报告准备好的进程。但是PostgreSQL服务器可能因为执行崩溃恢复而导致启动过程大大超过这个默认时间。建议的值是 0 禁用超时逻辑。

在NetBSD上,你可以根据爱好选择FreeBSD或Linux的启动脚本。

在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文件。这样做 可以防止多个服务器实例运行在同一个数据目录中,并且也可以被用来关闭服务器。

3.1. 服务器启动失败

有几个常见的原因会导致服务器启动失败。通过检查服务器日志或使用手工启动的方法(不做标准输出或标准错误的重定向), 就可以看到出现什么错误消息。下面我们详细地解释一些最常见的错误消息。


LOG:  could not bind IPv4 socket: 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 TCP/IP listen socket

正如这个消息所说的,这表示:你试图在一个已经有服务器运行着的端口上再启动另一个服务器。不过,如果核心错误消息不是Address already in use或其变体,那就有可能是别的问题。 例如,试图在一个被保留的端口上启动服务器会收到下面这样的消息:


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

像这样的消息:


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

可能意味着你的内核对共享内存区的限制小于PostgreSQL试图创建的工作区域(本例中是 4011376640 字节)。或者可能意味着根本就没有 System-V 风格的共享内存支持被配置在你的内核中。作为一种临时的解决方案, 你可以试着以小于正常数量的缓冲区(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)来绕开这个限制,但最终你还是会希望提高内核的限制。

如果你收到一个"illegal system call"错误, 那么很有可能是你的内核根本不支持共享内存或者信号量。这种情况下你唯一的选择就是重新配置内核并且把这些特性打开。

3.2. 客户端连接问题

尽管可能在客户端出现的错误情况范围宽广而且是应用相关的,但的确有几种与服务器的启动方式直接相关。除了下面提到的几种错误之外的问题都应该在相应的客户端应用文档中。


psql: could not connect to server: Connection refused
        Is the server running on host "server.joe.com" and accepting
        TCP/IP connections on port 5432?

这是常见的"I couldn't find a server to talk to"失败。上面的情况看起来是发生在尝试 TCP/IP 通信时。常见的错误是忘记把服务器配置成允许 TCP/IP 连接。

另外,当试图通过 Unix 域套接字与本地服务器通信时,你会看到这个:


psql: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

最后一行可以验证客户端是不是尝试连接到正确的位置。如果实际上没有服务器在那里运行,典型的核心错误消息将是Connection refused或No such file or directory(值得注意的是这种环境中的Connection refused并不表示服务器得到了你的连接请求并拒绝了它。那种情况会产生一个不同的消息)。其它像Connection timed out这样的消息可能表示更基础的问题,如缺少网络连接。

4. 管理内核资源

PostgreSQL某些时候会耗尽操作系统的各种资源限制,当同一个系统上运行着多个拷贝的服务器或在一个非常大的安装中时尤其如此。本节解释了PostgreSQL使用的内核资源以及你可以采取的用于解决内核资源消耗相关问题的步骤。

4.1. 共享内存和信号量

共享内存和信号量一起被称为"System V IPC"(其中还有消息队列,不过它与PostgreSQL无关)。除了在Windows上(PostgreSQL提供了自己的实现),这些功能都是运行PostgreSQL所必需的。

完全缺少这些功能通常表现为服务器启动时的Illegal system call错误。这种情况下,除了重新配置内核之外别无选择。PostgreSQL没有它们就不能工作。 不过,在现代操作系统中这种情况是罕见的。

当PostgreSQL超出了这些IPC的硬限制之一时,服务器会拒绝启动并且并且留下一条有指导性的错误消息,其中描述了问题以及应该怎么做。相关的内核参数在不同系统之间的命名方式一致,Table 18-1给出了一个概述。不过,设置它们的方法却多种多样。下面给出了对于某些平台的建议:

Note:
在PostgreSQL 9.3 之前,启动服务器所要求的 System V 共享内存的量要更大。如果你在运行着一个老版本的服务器,请参考该服务器版本的文档。

Table 18-1. System V IPC参数


image


PostgreSQL要求少量字节的 System V 共享内存(在 64 位平台上通常是 48 字节)用于每一个服务器拷贝。在大多数现代操作系统上,这个量很容易得到。但是,如果你运行了很多个服务器拷贝,或者其他应用也在使用 System V 共享内存,可能需要增加SHMMAX(以字节计的共享内存段的最大尺寸)或SHMALL(系统范围内 System V 共享内存的总量)。注意在很多系统上SHMALL是以页面而不是字节来度量。

不太可能出问题的是共享内存段的最小尺寸(SHMMIN),对PostgreSQL来说应该最多大约是 32 字节(通常只是1)。而系统范围(SHMMNI)或每个进程(SHMSEG)的最大共享内存段数目不太可能会导致问题,除非你的系统把它们设成零。

PostgreSQL对每个允许的连接(max_connections)、每个允许的自动清理工作者进程(autovacuum_max_workers)和每个允许的后台进程(max_worker_processes)使用一个信号量, 以16个为一个集合。每个这种集合还包含第 17 个信号量, 其中存储一个"magic number",以检测和其它应用使用的信号量集合的冲突。 系统里的最大信号量数目是由SEMMNS设置的, 因此这个值必须至少和max_connections加autovacuum_max_workers再加max_worker_processes一样大, 并且每 16 个连接外加工作者还要另外加一个(见Table 18-1中的公式)。参数SEMMNI 决定系统中同一时刻可以存在的信号量集合的数目限制。因此这个参数必须至少为ceil((max_connections + autovacuum_max_workers + max_worker_processes + 5) / 16)。降低允许的连接数目是一种临时的绕开失败(来自函数semget)的方法,通常使用让人混乱的措辞"No space left on device"。

在某些情况下可能还有必要增大SEMMAP,使之至少与SEMMNS相近。 这个参数定义信号量资源映射的尺寸,在其中每个连续的可用信号量块都需要一项。 每当一个信号量集合被释放,那么它要么会被加入到该与被释放块相邻的一个现有项,或者它会被注册在一个新映射项中。如果映射被填满,被释放的信号量将丢失(直到重启)。因此信号量空间的碎片时间长了会导致可用的信号量比应有的信号量少。

SEMMSL参数决定一个信号量集合中可以有多少信号量,对于PostgreSQL而言必须至少是 17。

许多其他设置与"semaphore undo"(信号量撤销)有关,例如SEMMNU和SEMUME,但不影响PostgreSQL。

AIX

至少到版本 5.1 为止,不再需要对这些参数(例如SHMMAX)做任何特殊的配置,这看起来就像是被配置成允许所有内存都被用作共享内存。这是一种通常被用于其他数据库(DB/2)的配置。

但是,可能需要修改/etc/security/limits中的全局ulimit信息,默认的文件尺寸硬限制(fsize)和文件数量(nofiles)可能太低。

FreeBSD

可以使用sysctl或loader接口来改变默认配置。下列参数可以使用sysctl设置:


# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728
# sysctl kern.ipc.semmap=256

要让这些设置在重启之后也保持,请修改/etc/sysctl.conf。

对于sysctl所关心的来说这些信号量相关的设置都是只读的,但是可以在/boot/loader.conf中设置:


kern.ipc.semmni=256
kern.ipc.semmns=512
kern.ipc.semmnu=256

修改这些值后需要一次重启让新设置能生效。 (注意:FreeBSD 不使用SEMMAP。较老的版本 会接受并且忽略kern.ipc.semmap的设置,而较新的 版本会完全拒绝它)。

你可能也希望你的内核将共享内存锁定在 RAM 中并且防止它被换页到交换分区。这可以使用sysctl的设置 kern.ipc.shm_use_phys来完成。

如果通过启用sysctl的security.jail.sysvipc_allowed运行在 FreeBSD jail 中,运行在不同 jail 中的postmaster应当被不同的操作系统用户运行。这可以提高安全性,因为它阻止非 root 用户干涉不同 jail 中的共享内存或信号量,并且它允许 PostgreSQL IPC 清理代码正确地工作(在 FreeBSD 6.0 及其后的版本中,IPC 清理代码不能正确地检测到其他 jail 中的进程,也不能阻止不同 jail 中的 postmaster 运行在相同的端口)。

FreeBSD 4.0 之前的版本的工作与OpenBSD相似(见下文)。

NetBSD

在NetBSD 5.0 及其后的版本中,IPC 参数可以使用sysctl调整。例如:


$ sysctl -w kern.ipc.shmmax=16777216

要使这些设置在重启后保持,请修改/etc/sysctl.conf。

你可能也希望你的内核将共享内存锁定在 RAM 中并且防止它被换页到交换分区。这可以使用sysctl的设置 kern.ipc.shm_use_phys来完成。

NetBSD 5.0 以前的版本的工作与OpenBSD相似(见下文),除了那些参数应该用关键词options设置而不是option。

OpenBSD

当内核被编译时,选项SYSVSHM和SYSVSEM需要被启用(它们默认值)。共享内存的最大尺寸由选项SHMMAXPGS(以页面计)决定。下面展示了一个如何设置多个参数的例子:


option        SYSVSHM
option        SHMMAXPGS=4096
option        SHMSEG=256

option        SYSVSEM
option        SEMMNI=256
option        SEMMNS=512
option        SEMMNU=256
option        SEMMAP=256

你可能也希望你的内核将共享内存锁定在 RAM 中并且防止它被换页到交换分区。这可以使用sysctl的设置 kern.ipc.shm_use_phys来完成。

HP-UX

默认的设置可以满足正常的安装。在HP-UX 10 上,SEMMNS的出厂默认值是 128,这可能对大型数据库站点太低。

IPC参数可以在Kernel Configuration->Configurable Parameters下的System Administration Manager(SAM)中被设置。当你完成时选择Create A New Kernel。

Linux

默认的最大段尺寸是 32 MB,并且默认的最大总尺寸是 2097152 个页面。一个页面几乎总是 4096 字节,除了在使用少见"huge pages"的内核配置中(使用getconf PAGE_SIZE来验证)。

共享内存尺寸设置可以通过sysctl接口来更改。例如,要允许 16 GB:


$ sysctl -w kernel.shmmax=17179869184
$ sysctl -w kernel.shmall=4194304

另外在重启之间这些设置可以被保存在文件/etc/sysctl.conf中。我们强烈推荐这样做。

古老的发型可能没有sysctl程序,但是可以通过操纵/proc文件系统来得到等效的更改:


$ echo 17179869184 >/proc/sys/kernel/shmmax
$ echo 4194304 >/proc/sys/kernel/shmall

剩下的默认值都被设置得很宽大,并且通常不需要更改。

OS X

在 OS X 中配置共享内存的推荐方法是创建一个名为/etc/sysctl.conf的文件,其中包含这样的变量赋值:


kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024

注意在某些 OS X 版本中,所有五个共享内存参数必须在/etc/sysctl.conf中设置,否则值将会被忽略。

注意近期的 OS X 版本会忽略把SHMMAX设置成非 4096 倍数值的尝试。

在这个平台上,SHMALL以 4kB 的页面度量。

在更老的 OS X 版本中,你将需要重启来让共享内存参数的更改生效。到了 10.5,可以使用sysctl随时改变除了SHMMNI之外的所有参数。但是最好还是通过/etc/sysctl.conf来设置你喜欢的值,这样重启之后这些值还能被保持。

只有在 OS X 10.3.9 及以后的版本中才遵循/etc/sysctl.conf文件。如果你正在使用 10.3.x 之前的发布,你必须编辑文件/etc/rc并且在下列命令中改变值:


sysctl -w kern.sysv.shmmax
sysctl -w kern.sysv.shmmin
sysctl -w kern.sysv.shmmni
sysctl -w kern.sysv.shmseg
sysctl -w kern.sysv.shmall

注意/etc/rc通常会被 OS X 的系统更新所覆盖,因此你应该在每次更新之后重做这些编辑。

在 OS X 10.2 及更早的版本中,应该在文件/System/Library/StartupItems/SystemTuning/SystemTuning中编辑这些命令。

SCO OpenServer

在默认的配置中,只允许每个段有 512kB 的共享内存。要增加这个设置,首先更改到目录/etc/conf/cf.d。要显示SHMMAX的当前值,运行:


./configure -y SHMMAX

要为SHMMAX设置一个新值,运行:


./configure SHMMAX=value

这里value是你要使用的新值(以字节计)。在设置SHMMAX之后,重新编译内核:


./link_unix

并且重启。

Solaris 2.6 至 2.9 (Solaris 6 至 Solaris 9)

相似的设置可以在/etc/system中更改,例如:

set shmsys:shminfo_shmmax=0x2000000
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=256
set shmsys:shminfo_shmseg=256

set semsys:seminfo_semmap=256
set semsys:seminfo_semmni=512
set semsys:seminfo_semmns=512
set semsys:seminfo_semmsl=32
你需要重启来让更改生效。关于更老版本的 Solaris 下的共享内存的信息请见http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html。

Solaris 2.10 (Solaris 10) 及以后
OpenSolaris

在 Solaris 10 及以后的版本以及 OpenSolaris 中,默认的共享内存和信号量设置已经足以应付大部分PostgreSQL应用。Solaris 现在将SHMMAX的默认值设置为系统 RAM的四分之一。要进一步调整这个设置,使用与postgres用户有关的一个项目设置。例如,以root运行下列命令:

projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres
这个命令增加user.postgres项目并且将用于postgres用户的最大共享内存设置为 8GB,并且在下次用户登录进来时或重启PostgreSQL(不是重新载入)时生效。上述假定PostgreSQL是由postgres组中的postgres用户所运行。不需要重新启动服务器。

对于将有巨大数量连接的数据库服务器,我们推荐的其他内核设置修改是:


project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)

此外,如果你正在在一个区中运行PostgreSQL,你可能也需要提升该区的资源使用限制。更多关于projects 和prctl的信息请见System Administrator's Guide中的 "Chapter2: Projects and Tasks"。

UnixWare

在UnixWare 7 上,默认配置中共享内存段的最大尺寸是 512 kB。要显示SHMMAX的当前值,运行:


/etc/conf/bin/idtune -g SHMMAX

这将显示当前值、默认值、最小值和最大值。要为SHMMAX设置一个新值,运行:


/etc/conf/bin/idtune SHMMAX value

这里value是你想要使用的新值(以字节计)。在设置SHMMAX之后,重新编译内核:


/etc/conf/bin/idbuild -B

并且重启。

4.2. 资源限制

Unix类操作系统强制了许多种资源限制,这些限制可能干扰你的PostgreSQL服务器的操作。尤其重要的是对每个用户的进程数目的限制、每个进程打开文件数目的限制以及每个进程可用的内存的限制。这些限制中每个都有一个"硬"限制和一个"软"限制。实际使用的是软限制,但用户可以自己修改成最大为硬限制的数目。而硬限制只能由root用户修改。系统调用setrlimit负责设置这些参数。 shell的内建命令ulimit(Bourne shells)或limit(csh)被用来从命令行控制资源限制。 在 BSD 衍生的系统上,/etc/login.conf文件控制在登录期间设置的各种资源限制。详见操作系统文档。相关的参数是maxproc、openfiles和datasize。例如:


default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

(-cur是软限制。增加-max可设置硬限制)。

内核也可以在某些资源上有系统范围的限制。

在Linux上,/proc/sys/fs/file-max决定内核可以支持打开的最大文件数。你可以通过往该文件写入一个不同的数值修改此值, 或者通过在/etc/sysctl.conf中增加一个赋值来修改。 每个进程的最大打开文件数限制是在编译内核的时候固定的;更多信息请见/usr/src/linux/Documentation/proc.txt。

PostgreSQL服务器为每个连接都使用一个进程, 所以你应该至少和允许的连接同样多的进程,再加上系统其它部分所需要的进程数目。 通常这个并不是什么问题,但如果你在一台机器上运行多个服务器,资源使用可能就会紧张。

打开文件的出厂默认限制通常设置为"socially friendly"的值, 它允许许多用户在一台机器上共存,而不会导致不成比例的系统资源使用。 如果你在一台机器上运行许多服务器,这也许就是你想要的,但是在专门的服务器上, 你可能需要提高这个限制。

在另一方面,一些系统允许独立的进程打开非常多的文件;如果不止几个进程这么干,那系统范围的限制就很容易被超过。如果你发现这样的现像, 并且不想修改系统范围的限制,你就可以设置PostgreSQL的 max_files_per_process配置参数来限制打开文件数的消耗。

4.3. Linux 内存过量使用

在 Linux 2.4 及其后的版本中,默认的虚拟内存行为对PostgreSQL不是最优的。由于内核实现内存过量使用的方法,如果PostgreSQL或其它进程的内存要求导致系统用光虚拟内存,那么内核可能会终止PostgreSQL的 postmaster 进程(主服务器进程)。

如果发生了这样的事情,你会看到像下面这样的内核消息(参考你的系统文档和配置,看看在哪里能看到这样的消息):

Out of Memory: Killed process 12345 (postgres).
这表明postgres进程因为内存压力而被终止了。尽管现有的数据库连接将继续正常运转,但是新的连接将无法被接受。要想恢复,PostgreSQL应该被重启。

一种避免这个问题的方法是在一台你确信其它进程不会耗尽内存的机器上运行PostgreSQL。 如果内存资源紧张,增加操作系统的交换空间可以帮助避免这个问题,因为内存不足(OOM)杀手(即终止进程这种行为)只有当物理内存和交换空间都被用尽时才会被调用。

如果PostgreSQL本身是导致系统内存耗尽的原因,你可以通过改变你的配置来避免该问题。在某些情况中,降低内存相关的配置参数可能有所帮助,特别是shared_buffers 和work_mem两个参数。在其他情况中,允许太多连接到数据库服务器本身也可能导致该问题。在很多情况下,最好减小max_connections并且转而利用外部连接池软件。

在 Linux 2.6 及其后的版本中,可以修改内核的行为,这样它将不会"过量使用"内存。尽管此设置不会阻止OOM 杀手被调用,但它可以显著地降低其可能性并且将因此得到更鲁棒的系统行为。这可以通过用sysctl选择严格的过量使用模式来实现:

sysctl -w vm.overcommit_memory=2
或者在/etc/sysctl.conf中放置一个等效的项。你可能还希望修改相关的设置vm.overcommit_ratio。 详细信息请参阅内核文档的https://www.kernel.org/doc/Documentation/vm/overcommit-accounting文件。

另一种方法,可以在改变或不改变vm.overcommit_memory的情况下使用。它将 postmaster 进程的进程相关的OOM score adjustment值设置为-1000,从而保证它不会成为 OOM 杀手的目标。 这样做最简单的方法是在 postmaster 的启动脚本中执行

echo -1000 > /proc/self/oom_score_adj
并且要在调用 postmaster 之前执行。请注意这个动作必须以 root 完成,否则它将不会产生效果。所以一个被 root 拥有的启动脚本是放置这个动作最容易的地方。如果这样做,你还应该在调用 postmaster 之前在启动脚本中设置这些环境变量:


export PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
export PG_OOM_ADJUST_VALUE=0

这些设置将导致 postmaster 子进程使用普通的值为零的 OOM score adjustment 运行,所以 OOM 杀手仍能在需要时把它们作为目标。如果你想要子进程用某些其他 OOM score adjustment 值运行,可以为PG_OOM_ADJUST_VALUE使用其他的值(PG_OOM_ADJUST_VALUE也能被省略,那时它会被默认为零)。如果你没有设置PG_OOM_ADJUST_FILE,子进程将使用和 postmaster 相同的 OOM score adjustment 运行,这是不明智的,因为重点是确保 postmaster 具有优先的设置。

更老的 Linux 内核不提供/proc/self/oom_score_adj,但是可能有一个具有相同功能的早期版本,它被称为/proc/self/oom_adj。这种方式工作起来完全相同,除了禁用值是-17而不是-1000。

Note:
有些厂商的 Linux 2.4 内核被报告有着 2.6 过量使用sysctl参数的早期版本。不过,在没有相关代码的 2.4 内核里设置vm.overcommit_memory为 2 将会让事情更糟。我们推荐你检查一下实际的内核源代码(见文件mm/mmap.c中的vm_enough_memory函数),验证一下这个是在你的内核中是被支持的, 然后再在 2.4 安装中使用它。文档文件overcommit-accounting的存在不能当作是这个特性存在的证明。如果有疑问,请咨询一位内核专家或你的内核厂商。

4.4. Linux 大页面

在PostgreSQL使用大量 连续内存块时利用大页面来降低开销。要在 PostgreSQL中启用这个 特性,你需要一个 CONFIG_HUGETLBFS=y并且 CONFIG_HUGETLB_PAGE=y的内核。 你也还必须调节系统设置 vm.nr_hugepages。要估计所需的 大页面的数量,关闭大页面启动 PostgreSQL并且从 proc 文件系统检查VmPeak值:


$ head -1 /path/to/data/directory/postmaster.pid
4170
$ grep ^VmPeak /proc/4170/status
VmPeak:  6490428 kB

6490428 / 2048 (在这种情况下PAGE_SIZE是 2MB)大约是 3169.154个大页面,因此你将需要至少 3170个大页面:


$ sysctl -w vm.nr_hugepages=3170

有时候内核会无法分配想要的数量的大页面,所以可能有必要 重复该命令或者重新启动。不要忘了向 /etc/sysctl.conf中增加一个项来让这 个设置重启后也能保持。

有必要给予数据库服务器操作系统用户权限,让他能通过sysctl设置vm.hugetlb_shm_group以使用大页面,以及用ulimit -l锁定内存的权限。

PostgreSQL中大页面的默认行为是 尽可能使用它们并且在失败时转回到正常页面。要强制使用大页面,你可 以把 huge_pages设置成 on。注意在这种情况下如果没有足够的大页面可用, PostgreSQL将会启动失败。

Linux大页面特性的详细描述可见https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.

5. 关闭服务器

有几种关闭数据库服务器的方法。通过给postgres进程发送不同的信号,你就可以控制关闭类型。

SIGTERM

这是智能关闭模式。在接收SIGTERM后, 服务器将不允许新连接,但是会让现有的会话正常结束它们的工作。仅当所有的会话终止后它才关闭。 如果服务器处在线备份模式,它将等待直到在线备份模式不再被激活。当在线备份模式被激活时, 仍然允许新的连接,但是只能是超级用户的连接(这一例外允许超级用户连接来终止在线备份模式)。 如果服务器在恢复时请求智能关闭,恢复和流复制只有在所有正常会话都终止后才停止。

SIGINT

这是快速关闭模式。服务器不再允许新的连接,并向所有现有服务器进程发送SIGTERM,让它们中断当前事务并立刻退出。然后服务器等待所有服务器进程退出并最终关闭。 如果服务处于在线备份模式,备份模式将被终止并致使备份无用。

SIGQUIT

这是立即关闭模式。服务器将给所有子进程发送 SIGQUIT并且等待它们终止。如果有任何进程没有在 5 秒内终止,它们将被发送 SIGKILL。主服务器进程将在所有子进程退出之后立刻退出,而无需做普通的数据库关闭处理。这将导致在下一次启动时(通过重放 WAL 日志)恢复。只在紧急 时才推荐这种方式。

pg_ctl程序提供了一个发送这些信号关闭服务器的方便的接口。 另外,你在非 Windows 系统上可以用kill直接发送这些信号。可以用ps程序或者从数据目录的postmaster.pid文件中找到postgres进程的PID。例如,要做一次快速关闭:


$ kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`

Important: 最好不要使用SIGKILL关闭服务器。 这样做将会阻止服务器释放共享内存和信号量,那么在开始一个新的服务器之前,可能需要手动完成这些释放。 此外,使用SIGKILL杀掉postgres进程时,postgres不会有机会将信号传播到它的子进程,所以也必须手工杀掉单个的子进程。

要终止单个会话同时允许其他会话继续,使用pg_terminate_backend()(参阅Table 9-77) 或发送SIGTERM信号到该会话相关的子进程。

6. 升级一个PostgreSQL集簇

本节讨论如何把你的数据库数据从一个PostgreSQL发行升级到一个更新的发行。

PostgreSQL主版本用版本号的前两个数字组表示,例如 8.4。PostgreSQL次要版本则由第三组版本数字表示,例如 8.4.2 是 8.4 的第二个次要发行。次要发行从来不改变内部存储格式并且总是向前并向后兼容同一主版本号中的次要发行,例如 8.4.2 与 8.4、8.4.1、8.4.6 兼容。要在兼容的版本间升级,你只需要简单地在服务器关闭时替换可执行文件并重启服务器。数据目录则保持不变 — 次要升级就这么简单。

对于PostgreSQL的主发行, 内部数据存储格式常被改变,这使升级复杂化。传统的把数据移动到 新主版本的方法是先转储然后重新载入到数据库,不过这可能会很慢。 一种更快的方式是pg_upgrade。如下文所讨论的, 复制方法也能被用于升级。

新的主版本也通常会引入一些用户可见的不兼容性,因此可能需要应用程序编程上的改变。所有用户可见的更改都被列在发行注记(Appendix E)中,请特别注意标有 "Migration" 的小节。如果你正在跨越几个主版本升级,一定要阅读每个中间版本的发行注记。

小心的用户在完全切换过去之前将希望在新版本上测试他们的客户端应用。因此,建立一个新旧版本的并存安装通常是一个好主意。在测试一个PostgreSQL主要升级时,考虑下列可能的改变类别:

管理

用于管理员监控和控制服务器的功能在每一个主发行中经常会改变和增加。

SQL

通常这包括新的 SQL 命令功能并且在行为上没有更改,除非在发行注记中有特别提到。

库 API

通常libpq等库值增加新功能,除非在发行注记中有特别提到。

系统目录

系统目录改变通常只影响数据库管理工具。

服务器 C-语言 API

这涉及到后端函数 API 中的改变,它使用 C 编程语言编写。这些改变影响引用服务器内部后端函数的代码。

6.1. 通过pg_dumpall升级数据

一种升级方法是从PostgreSQL的一个主版本转储数据并将它重新载入到另一个主版本中 — 要这样做,你必须使用pg_dumpall这样的逻辑备份工具,文件系统级别的备份方法将不会有用(这也阻止你在一个不兼容版本的PostgreSQL中使用一个数据目录,因此在一个数据目录上尝试启动一个错误的服务器版本不会造成很大的危害)。

我们推荐你从较新版本的PostgreSQL中使用pg_dump和pg_dumpall程序,这样可以利用在这些程序中可能存在的改进。当前发行的转储程序可以读取任何 7.0 以上版本服务器中的数据。

这些指令假定你现有的安装位于/usr/local/pgsql目录,并且数据区域在/usr/local/pgsql/data。请用你的路径进行适当的替换。

1.如果在创建一个备份,确认你的数据库没有在被更新。这不会影响备份的完整性,但是那些更改当然不会被包括在备份中。如果必要,编辑/usr/local/pgsql/data/pg_hba.conf文件中的权限(或等效的方法)来不允许除你之外的任何人使用数据库。关于访问控制的额外信息请见Chapter 20。

要备份你的数据库安装,键入:


pg_dumpall > outputfile

要制作备份,你可以使用你正在运行版本的pg_dumpall命令,详见Section 25.1.2。但是,要得到最好的结果,试试使用PostgreSQL 9.6.0 的pg_dumpall命令,因为这个版本包含了对旧版本的缺陷修复和改进。虽然这个建议可能看起来很奇怪,因为你还没有安装新版本,但如果你计划平行地安装新版本,遵循这个建议是很明智的。在这种情况下,你可以正常完成安装并且稍后再来传输数据。这也将减少停机时间。

2.关闭就服务器:


pg_ctl stop

在那些自动启动PostgreSQL的系统上,可能有一个启动文件将完成同样的事情。例如,在一个Red Hat Linux系统中,我们会发现这也能用:


/etc/rc.d/init.d/postgresql stop

3.如果从备份恢复,重命名或删除旧的安装目录(如果它不是针对特定版本的)。重命名该目录是一个好主意,而不是删除它,因为如果你碰到问题并需要返回到它,它还存在。记住该目录可能消耗可观的磁盘空间。要重命名该目录,使用类似的命令:


mv /usr/local/pgsql /usr/local/pgsql.old

(注意将该目录作为一个单一单元移动,这样相对路径可以保持不变)。

4.安装新版本的PostgreSQL在 Section 16.4.

5.如果需要,创建一个新的数据库集簇。记住你必须在登录到一个特殊的数据库用户账户(如果你在升级,你就已经有了这个账户)时执行这些命令。


/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data

6.恢复你之前的pg_hba.conf以及任何postgresql.conf修改。

7.启动数据库服务器,也要使用特殊的数据库用户账户:


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

8.最后,使用新的 psql从备份恢复你的数据:

/usr/local/pgsql/bin/psql -d postgres -f outputfile
通过在一个不同的目录中安装新的服务器并且并行地在不同的端口运行新旧两个服务器可以达到最低的停机时间。那么你可以这样用:


pg_dumpall -p 5432 | psql -d postgres -p 5433

来转移你的数据。

6.2. 通过pg_upgrade升级数据

pg_upgrade模块允许一个安装从一个 PostgreSQL主版本“就地”升级成另一个主版本。 升级可以在数分钟内被执行,特别是使用--link模式时。它 要求和上面的pg_dumpall相似的步骤,例如启动/停止 服务器、运行initdb。pg_upgrade 文档概述了所需的步骤。

6.3. 通过复制升级数据

也可以使用某些复制方法来使用PostgreSQL的已更新版本创建一个后备服务器,例如Slony,它支持在不同主版本的PostgreSQL之间的复制。后备服务器可以在同一台计算机或者不同的计算机上。一旦它和主服务器(运行旧版本的PostgreSQL)同步好,你可以切换主机并且将后备服务器作为主机,然后关闭旧的数据库实例。这样一种切换使得一次升级的停机时间只有数秒。

7. 阻止服务器欺骗

服务器在运行时,它不可能让恶意用户取代正常的数据库服务器。然而,当服务器关闭时, 一个本地用户可以通过启动它们自己的服务器来欺骗正常的服务器。行骗的服务器可以读取客户端发送的密码和查询语句, 但是不会返回任何数据,因为PGDATA这个目录是安全的(它有目录权限)。 欺骗是可能的,因为任何用户都可以启动一个数据库服务器;客户端无法识别一个无效的服务器,除非它被专门配置。

一种阻止local连接欺骗的方法是使用一个 Unix 域套接字目录 (unix_socket_directories),该目录只对一个被信任的本地用户有写权限。 这可以防止恶意用户在该目录中创建自己的套接字文件。如果你担心有些应用程序可能仍然引用/tmp下的套接字文件并且因此容易受到欺骗,可在操作系统启动时创建一个符号链接/tmp/.s.PGSQL.5432指向一个被重定位的套接字文件。你也可能需要修改/tmp清除脚本防止删除这个符号链接。

local连接的另一个选项是对客户端使用requirepeer指定所需的连接到该套接字的服务器进程的拥有者。

要在TCP连接上防止欺骗,最好的解决方案是使用 SSL 证书,并且确保客户检查服务器的证书。 要做到这点,服务器必须配置为仅接受hostssl连接,并且有 SSL 密钥和证书文件。 TCP 客户端连接必须使用sslmode=verify-ca或verify-full进行连接,并且安装有适当的根证书文件。

8. 加密选项

PostgreSQL提供了几个不同级别的加密, 并且在保护数据不会因为数据库服务器偷窃、不道德的管理员、不安全网络等因素而泄漏方面 提供很高的灵活性。加密可能也是保护一些诸如医疗记录或财务交易等敏感数据所要求的。

口令存储加密

默认情况下,数据库用户的口令以 MD5 哈希的方式存储, 所以管理员无法判断赋予用户的实际口令。如果 MD5 被加密用于客户端认证, 那么未加密的口令甚至都不可能临时出现在服务器上,因为客户端在透过网络发送口令之前,就先用 MD5 加密过。

指定列加密

pgcrypto模块允许对特定域进行加密存储。这个功能只对某些敏感数据有用。 客户端提供解密的密钥,然后数据在服务器端解密并发送给客户端。

在数据被解密和在服务器与客户端之间传递时,解密数据和解密密钥将会在服务器端存在短暂的一段时间。 这就给那些能完全访问数据库服务器的人提供了一个短暂的截获密钥和数据的时间,例如系统管理员。

数据分区加密

存储加密可以在文件系统层面或者块层面上执行。Linux 文件系统加密 选项包括 eCryptfs 和 EncFS,而 FreeBSD 使用 PEFS。快层面或者全 盘加密选项包括 Linux 上的 dm-crypt + LUKS 以及 FreeBSD 上的 GEOM 模块 geli 及 gbde。很多其他操作系统也支持这个功能,包括 Windows。

这个机制避免了在整个计算机或者驱动器被盗的情况下, 未加密的数据被从驱动器中读取。它无法防止在文件系统被挂 载时的攻击,因为在挂载之后,操作系统提供数据的解密视图。不过,要想挂载该文件系统,你需要有一些方法把加密密钥传递给操作 系统,并且有时候这个密钥就存储在挂载该磁盘的主机上的某处。

跨网络加密口令

MD5认证方法在将口令发送给服务器之前由客户端对它进行双重加密。第一次 MD5 加密是基于用户名的, 然后在建立数据库连接时,用服务器发送的随机盐粒再次加密口令。通过网络传递给服务器的就是这个双重加密的值。双重加密 不仅可以防止口令被发现,还可以防止稍后另一个连接使用同样的加密口令连接数据库。

跨网络加密数据

SSL 连接加密所有跨网络发送的数据:口令、查询以及返回的数据。pg_hba.conf文件允许管理员指定哪些主机可以使用 非加密连接(host),以及哪些主机需要使用 SSL 加密的连接(hostssl)。客户端还可以指定它们只通过 SSL 连接到服务器。我们还可以使用Stunnel或SSH加密传输。

SSL 主机认证

客户端和主机都可以提供 SSL 证书给对方。这在两边都需要一些额外的配置, 但是这种方式提供了比仅使用口令更强的身份验证。 它避免一个计算机伪装成服务器,这个时长只要足够读取客户端发送的口令就行了。它还避免了 "中间人"攻击,在其中有一台计算机处于客户端和服务器之间并伪装成服务器读取和传递两者之间的所有数据。

客户端加密

如果服务器所在机器的系统管理员是不可信的,那么客户端加密数据也是必要的。在这种情况下,未加密的数据从来不会在数据库服务器上出现。数据在发送给服务器之前加密,而数据库结果在能使用之前必须在客户端上解密。

9. 用 SSL 进行安全的 TCP/IP 连接

PostgreSQL有一个对使用SSL连接加密客户端/服务器通讯的本地支持,它可以增加安全性。这个特性要求在客户端和服务器端都安装OpenSSL并且在编译PostgreSQL的时候打开这个支持(见Chapter 16)。

当SSL支持被编译在PostgreSQL中时,可以通过将postgresql.conf中的 ssl设置为on让PostgreSQL服务器带着SSL支持被启动。 服务器在同一个 TCP 端口监听普通连接和SSL连接,并且将与任何正在连接的客户端协商是否使用SSL。默认情况下,这是客户端的选项,关于如何设置服务器来要求某些或者所有连接使用SSL请见Section 20.1。

PostgreSQL读取系统范围的OpenSSL配置文件。默认情况下,这个文件名为openssl.cnf并且被放置在openssl version -d所报告的目录中。通过设置环境变量OPENSSL_CONF指定你想要的配置文件名可以覆盖此默认配置。

OpenSSL支持范围广泛的密码和认证算法。而在OpenSSL配置文件可以指定一个密码列表, 你可以通过在postgresql.conf中修改ssl_ciphers来指定数据库服务器使用的专用密码。

Note: 使用NULL-SHA或NULL-MD5可以得到身份验证但没有加密开销。不过,中间人能够读取和传递客户端和服务器之间的通信。此外,加密开销相比身份认证的开销是最小的。出于这些原因,我们建议不要使用 NULL 密码。

要SSL模式中启动服务器,包含服务器证书和私钥的文件必须存在。默认情况下,这些文件应该分别被命名为server.crt和server.key并且被放在服务器的数据目录中,但是可以通过配置参数ssl_cert_file和ssl_key_file指定其他名称和位置。

在 Unix 系统上,server.key上的权限必须不允许所有人或组的任何访问,通过命令chmod 0600 server.key可以做到。或者,该文件可以由 root 所拥有并且具有组读访问(也就是0640权限)。这种设置适用于由操作系统管理证书和密钥文件的安装。用于运行PostgreSQL服务器的用户应该被作为能够访问那些证书和密钥文件的组成员。

如果私钥被一个密码保护着,服务器将提示要求这个密码,并且在它被输入前不会启动。

在有些情况下,服务器证书可能由一个"中间" 证书颁发机构签名,而不是直接由客户端信任的证书颁发 机构直接签名。要使用这样的证书,请追加该签发权的证书到server.crt文件,然后追加其父签发权的证书,以此类推一直到一个被客户端所信任的"根"或"中间"颁发机构,即由一个位于客户端root.crt文件中的证书签发。

9.1. 使用客户端证书

要求客户端提供受信任的证书,把你信任的证书颁发机构(CA)的证书放置在数据目录的文件root.crt中。并且修改postgresql.conf中的参数ssl_ca_file为root.crt,还要把认证选项clientcert=1加入到pg_hba.conf文件中合适的hostssl行上。然后将在 SSL 连接启动时从客户端请求该证书(一段对于如何在客户端设置证书的描述请见Section 32.18)。服务器将验证客户端的证书是由受信任的证书颁发机构之一签名。

如果中间CA出现在root.crt中,该文件必须也包含到它们的根CA的证书链。如果参数ssl_crl_file被设置,证书撤销列表(CRL)项也要被检查(显示 SSL 证书用法的图标见http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s02.html)。

clientcert认证选项适用于所有的认证方法,但仅适用于pg_hba.conf中用hostssl指定的行。 当clientcert没有指定或设置为 0时,如果配置了 CA 文件,服务器将仍然会根据它验证任何提交的客户端证书 — 但是它将不会坚持要求出示一个客户端证书。

请注意服务器的root.crt列出了顶级的 CA,它们对客户端证书的签名被认为是可信的。 原则上不需要列出签名服务器证书的 CA,然而在大多数情况下,这些 CA 对于客户端证书也是可信的。

如果你在设置客户端证书,你可能希望用cert认证方法,这样证书控制用户认证以及提供连接安全(在使用cert认证方法时,没有必要显式地指定clientcert=1)。

9.2. SSL 服务器文件用法

Table 18-2总结了与服务器上 SSL 配置有关的文件(显示的文件名是默认的或者是经典名称。本地配置的名称可能会不同)。

Table 18-2. SSL 服务器文件用法

image


文件server.key、server.crt、root.crt和root.crl(或者被配置的其他名字)只在服务器启动期间被检查,所以要使对它们的修改生效,你必须重启服务器。

9.3. 创建自签名的证书

要为服务器创建一个快速的自签名的证书,可以使用下面的OpenSSL命令:


openssl req -new -text -out server.req

填充那些openssl要求的信息。确保把本地主机名当做"Common Name"输入;挑战密码可以留空。 该程序将生成一个用口令保护的密钥,它不会接受小于四字符的口令。要移去密钥(如果你想自动启动服务器就必须这样),运行下面的命令:


openssl rsa -in privkey.pem -out server.key
rm privkey.pem

输入旧口令解锁现有密钥。然后:


openssl req -x509 -in server.req -text -key server.key -out server.crt

将一个证书变成自签名的证书并复制密钥和证书到服务器将要查找它们的地方。最后执行:


chmod og-rwx server.key

如果文件的权限比这个更自由,服务器将拒绝该文件。要了解更多关于如何创建你的服务器私钥和证书的细节, 请参考OpenSSL文档。

自签名的证书可以被用于测试,但由证书颁发机构(CA)(要么是全局CA中的一个或者一个本地 CA)签名的证书应该被用在生产中,这样客户端可以验证服务器的身份。如果对于组织来说所有的客户端都是本地的,建议使用本地CA。

10. 使用SSH隧道的安全 TCP/IP 连接

可以使用SSH来加密客户端和PostgreSQL服务器之间的网络连接。如果处理得当,这将提供一个足够安全的网络连接,即使是对那些无 SSL 能力的客户端。

首先确认在PostgreSQL服务器的同一台机器上正确运行着一个SSH服务器,并且你可以使用ssh作为某个用户登入。然后你可以从客户端机器采用下面这种形式的命令建立一个安全的隧道:


ssh -L 63333:localhost:5432 joe@foo.com

-L参数中的第一个数(63333)是隧道在你那一端的端口号,它可以是任意未用过的端口(IANA 把端口 49152 到 65535 保留为个人使用)。第二个数(5432)是隧道的远端:你的服务器所使用的端口号。在端口号之间的名字或 IP 地址是你准备连接的数据库服务器的主机,至于你是从哪个主机登入的,在这个例子中则由foo.com表示。为了使用这个隧道连接到数据库服务器,你在本地机器上连接到端口 63333:


psql -h localhost -p 63333 postgres

对于数据库服务器,在这个环境中它将把你看做是连接到localhost的主机foo.com上的真实用户joe,并且它会使用被配置用于来自这个用户和主机的连接的认证过程。注意服务器将不会认为连接是 SSL 加密的,因为事实上SSH服务器和PostgreSQL服务器之间没有加密。只要它们在同一台机器上,这就不会造成任何额外的安全风险。

为了让隧道设置成功,你必须允许通过ssh作为joe@foo.com连接,就像你已经尝试使用ssh来创建一个终端会话。

你应当也已经设定好了端口转发:


ssh -L 63333:foo.com:5432 joe@foo.com

但是数据库服务器则将会看到连接从它的foo.com接口进来,它没有被默认设置listen_addresses = 'localhost'所打开。这通常不是你想要的。

如果你必须通过某个登录主机"跳"到数据库服务器,一个可能的设置看起来像:


ssh -L 63333:db.foo.com:5432 joe@shell.foo.com

注意这种从shell.foo.com到db.foo.com的连接的方法将不会被 SSH 隧道加密。当网络被限制于各种方法时,SSH 提供了相当多的配置可能性。详情请参考 SSH 的文档。

Tip: 一些其他的应用可以提供安全隧道,它们使用和刚刚描述的 SSH 概念上相似的过程。

11. 在Windows上注册Event Log

要为操作系统注册一个Windows 事件日志库,发出这个命令:


regsvr32 pgsql_library_directory/pgevent.dll

这会创建被事件查看器使用的注册表项,默认事件源命名为PostgreSQL。

要指定一个不同的事件源名称(见event_source)。使用/n和/i选项:


regsvr32 /n /i:event_source_name pgsql_library_directory/pgevent.dll

要从操作系统反注册事件日志库,发出这个命令:


regsvr32 /u [/i:event_source_name] pgsql_library_directory/pgevent.dll

Note:
要启用数据库服务器中的事件日志,在postgresql.conf中修改log_destination来包括eventlog。

版权声明:本文内容由互联网用户自发贡献,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

用云栖社区APP,舒服~

【云栖快讯】红轴机械键盘、无线鼠标等753个大奖,先到先得,云栖社区首届博主招募大赛9月21日-11月20日限时开启,为你再添一个高端技术交流场所  详情请点击

网友评论

关注
琴瑟
TA有点害羞,没有介绍自己...
302篇文章|61关注
一款安全易用的管理类服务。您无需花费大量成本来保护密钥的保密性、完整性和可用性,借助密钥管理服务,您可以安全、便... 更多>

PostgreSQL被业界誉为“最先进的开源数据库”,面向企业复杂SQL处理的OLTP在线事务处理场景,支持No... 更多>

操作审计(ActionTrail)会记录您的云账户资源操作,提供操作记录查询,并可以将记录文件保存到您指定的OS... 更多>

为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本... 更多>
MaxCompute75折抢购

MaxCompute75折抢购