Chapter 3. 服务器运行时环境
Table of Contents
3.1. PostgreSQL 用户帐户
3.2. 创建数据库集群
3.3. 启动数据库服务器
3.3.1. 服务器启动失败
3.3.2. 客户端联接问题
3.4. 运行时配置
3.4.1. pg_settings
3.4.2. 规划器和优化器调节
3.4.3. 日志和调试
3.4.4. 一般操作
3.4.5. WAL
3.4.6. 短选项
3.5. 管理内核资源
3.5.1. 共享内存和信号灯
3.5.2. 资源限制
3.6. 关闭服务器
3.7. 用 SSL 进行安全的 TCP/IP 联接
3.8. 用SSH进行安全 TCP/IP 联接
本章讨论如何设置和运行数据库服务器以及如何与操作系统交互.
3.1. PostgreSQL 用户帐户
和大量其它与外界相联的服务器守护进程一样,我们也建议 用一个独立的用户帐户运行PostgreSQL.这个用户帐户应该拥有 由这个服务器管理的数据,而且不应该与其他守护进程共享这些数据. (比如,用"nobody" 用户是个烂主意.) 我们不建议把可执行文件安装为由此用户所有, 因为这样一来被攻破的系统就可以修改它们自己拥有的二进制文件.
要向你的系统里增加用户帐户,参考命令 useradd 或 adduser. 我们经常使用 postgres 的用户名,但并不是必须的.
3.2. 创建数据库集群
在你做任何事情之前,你必须初始化磁盘上的数据库的存储区间. 我们管它叫数据库集群. (SQL 使用术语目录集群.) 一个数据库集群是一系列数据库的集合,这些数据库可以通过 单个数据库服务器的实例访问.在初始化后,一个数据库集群 将包含一个叫template1的数据库. 正如其名一样,这个数据库将作为随后创建的数据库的 模版;在实际工作中不应该使用这个库. (参阅 Chapter 7 获取有关创建数据库的信息。)
用文件系统的术语来说,一个数据库集群将是一个目录,所有数据都 将存放在这个目录中.我们把它称做 数据目录 或 数据区 .在哪里存放数据完全是你的选择,我们没有缺省值,尽管 /usr/local/pgsql/data 或 /var/lib/pgsql/data 这样的目录很常用. 要初始化一个数据库集群,可以使用命令 initdb, 这个命令于 PostgreSQL一起安装.你可以用-D 标识你为你的数据库系统选择的文件系统位置,例如
$ initdb -D /usr/local/pgsql/data
请注意你必须以PostgreSQL用户的身份来执行这条命令, 这一点我们在前面一节描述过.
技巧: 作为 -D选项的替代品,你还可以使用环境变量 PGDATA.
如果你声明的路径还不存在, initdb 将试图创建它. 你很有可能缺少做这些事情的权限(如果你按照我们的建议 创建了一个非特权帐户的话).这时,你可以自己创建该目录(以root身份) 然后把该目录的所有权交给PostgreSQL用户或者赋与她写权限. 下面是可能有效的方法:
root# mkdir /usr/local/pgsql/data
root# chown postgres /usr/local/pgsql/data
root# su postgres
postgres$ initdb -D /usr/local/pgsql/data
如果数据目录看起来象已经属于某个已初始化的安装了,那么 initdb 会拒绝运行.
因为数据目录包含所有存储在数据库里的数据,所以出于安全 考虑,这个目录不能给任何非授权用户范围.因此, initdb 禁止除PostgreSQL 用户帐户以外的任何用户访问这个目录.
不过,因为目录的内容是安全的,所以缺省的客户端认证设置 允许任意局部用户联接到数据库甚至成为超级用户. 如果你不信任你的本地用户,我们建议你使用 initdb 的选项 -W 或者 --pwprompt 给 超级用户赋予一个口令.在 initdb 之后, 在你第一次启动服务器之前 修改 pg_hba.conf,让它使用 md5 或者 password,而不是 trust 认证方式. (另外一些方法包括 ident 认证或者 用文件系统权限限止联接.参阅 Chapter 4 获取更多细节.)
initdb 同时也为数据库集群初始化区域. 通常,它将只是使用环境中的区域设置并且把它们应用与初始化的数据库. 我们可以为数据库声明不同的区域;有关这些的更多信息可以在 Section 5.1 中找到. 运行 initdb 的时候你可能碰到的一件奇怪的事情是 看到下面这样的注意信息:
WARNING: Initializing database with en_US collation order.
This locale setting will prevent use of index optimization for
LIKE and regexp searches. If you are concerned about speed of
such queries, you may wish to set LC_COLLATE to "C" and
re-initdb. For more information see the Administrator's Guide.
这条注意信息主要是警告你目前所用的区域设置将把索引按照 一种无法用于LIKE和正则表达式搜索的方式存储. 如果你执行这样的搜索时需要高性能的话,你应该把当前区域设置设 为 "C" 然后重新运行 initdb. 也就是说,运行 initdb --lc-collate=C. 在特定数据库集群里的排序顺序是由 initdb 设置的, 而且以后就不能更改了,除非转储所有数据,重新运行initdb, 并重新装载数据.因此在这个阶段做决定很有必要.
3.3. 启动数据库服务器
在任何人可以访问数据库前,你必须启动数据库服务器.数据库 服务器叫 postmaster. postmaster 必须知道到哪里能找到她要用的数据.这是利用 -D选项来实现的.因此,启动服务器的最简单 的方法是,比如象下面这样∶
$ postmaster -D /usr/local/pgsql/data
这样将把服务器放在前台运行.这个步骤同样必须以PostgreSQL 用户帐户登录来做.没有 -D 选项,服务器将使用 环境变量 PGDATA;如果两个都没有, 服务器将失败(退出).
要在后台启动 postmaster, 使用下面的 shell 语法:
$ postmaster -D /usr/local/pgsql/data > logfile 2>&1 &
把服务器的stdout和stderr放到某个地方 是非常重要的,就象在上面 建议的这样.这样做既可以帮助审计又可以帮助诊断问题. (参阅 Section 8.4 获取有关日志文件 处理的更完整的讨论.)
postmaster 还接受一些其他的一些命令行选项.更多的信息请参考 手册页和下面的 Section 3.4.尤其要注意的一点是, 为了令服务器 接受 TCP/IP 联接(而不仅仅是 Unix 域套接字),你必须声明 -i选项.
这些 shell 语法很容易让人觉得无聊.因此我们提供了 shell 脚本封装 pg_ctl 以简化一些 任务.比如,
pg_ctl start -l logfile
将在后台启动服务器并且把输出放到指定的日志文件中. -D 选项和你直接运行 postmaster 时的意思是一样的. pg_ctl 还可以用于关闭服务器.
通常,你会希望在计算机启动的时候启动数据库服务器. 自动启动脚本是与操作系统相关的. PostgreSQL 自己带了几个, 放在 /contrib/start-scripts 目录里. 我们可能需要 root 权限.
不同的系统在引导的时候有不同的启动守护进程的方法,所以 我们建议你先熟悉它们.许多系统有名字称为 /etc/rc.local 或 /etc/rc.d/rc.local 这样的文件, 其它的还有 rc.d 目录. 不管你怎么干,都要记住服务器必须以 PostgreSQL 用户帐户而不是以 root或者其他任何用户的身份运行. 这样,你可能总是要用下面这行的样子构造你的命令: su -c '...' postgres.比如:
su -c 'pg_ctl -D /usr/local/pgsql/data -l serverlog' postgres
下面是一些比较详细的与操作系统相关的建议.(请注意 把这些替换成合适的安装路径和用户名.)
*
对于 FreeBSD,看看 PostgreSQL 源代码版本里的文件 contrib/start-scripts/freebsd.
*
在 OpenBSD上, 把下面几行加到文件 /etc/rc.local 里:
if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postmaster ]; then
su - -c '/usr/local/pgsql/bin/pg_ctl start -l /var/postgresql/log -s' postgres
echo -n ' postgresql'
fi
*
在 Linux 系统里,要么往 /etc/rc.d/rc.local 文件里加上下面几行:
/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data
要么看看 PostgreSQL 程序版本里 的文件 contrib/start-scripts/linux,
*
在 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.
postmaster 运行的时候,它的PID是数据目录里的文件 postmaster.pid 的内容.这样做是为了避免多个 postmaster 在 同一个数据目录内运行,此文件同样可以用于关闭 postmaster.
3.3.1. 服务器启动失败
有几个非常常见的原因会导致 postmaster 启动失败. 通过检查 postmaster 日志或者使用手工启动的方法(不做 stdout和stderr 的重定向),就可以看到错误信息.有些错误信息是自明的, 不过还有一些不是.如下所述∶
FATAL: StreamServerPort: bind() failed: Address already in use
Is another postmaster already running on that port?
就象它提示的那样:你试图在已经有一个 postmaster 运行着的 端口上再运行了一个 postmaster.不过,如果内核的错误信息 不是Address already in use 或者是其它的变种,那就有可能是别的毛病. 比如,试图在一个保留的端口上运行 postmaster 会收到下面这样的信息
$ postmaster -i -p 666
FATAL: StreamServerPort: bind() failed: Permission denied
Is another postmaster already running on that port?
象这样的信息
IpcMemoryCreate: shmget(key=5440001, size=83918612, 01600) failed: Invalid argument
FATAL 1: ShmemCreate: cannot create region
可能意味着你的内核对共享内存区的限制小于PostgreSQL 试图分配的 缓冲区大小(本例中是 83918612 字节).或者可能意味着你根本 就没有配置 System-V 风格的共享内存支持.作为一个临时的解决办法, 你可以试着以小于正常数量的缓冲区数(-B开关) 启动 postmaster.你最终还是会希望重新配置你的内核,以 增加共享内存的尺寸.如果你试图在同一台机器上启动多个 postmaster, 而且她们所需的总空间超过了内核的限制,也会报这个错.
象下面这样的错误
IpcSemaphoreCreate: semget(key=5440026, num=16, 01600) failed: No space left on device
并不意味着着你已经用光磁盘空间了.它的意思是 你的内核的 System V 信号灯的限制小于 PostgreSQL 想创建的数量.和上面一样,你可以通过减少允许的连接数 (-N开关)来绕开,但最终你还是会希望增加 内核的限制.
如果你收到一个 "illegal system call" 错误,那么很有可能是 你的相同根本不支持共享内存或者信号灯.如果是这样的话,你的唯一选择 就是重新配置你的内核并且把这些特性打开.
关于配置系统System V IPC资源的细节见 Section 3.5.1.
3.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?
这是纯粹的 "我找不到可以交谈的服务器 "错误.当试图进行 TCP/IP 通讯时 它看起来象上面的样子. 常见的错误是忘记带 -i 启动 postmaster 以允许 TCP/IP 联接.
另外,当试图通过一个 Unix 套接字与本机 postmaster 通讯时,你会看到这个:
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?
and accepting connections on Unix socket '/tmp/.s.PGSQL.5432'?
最后一行可以有效地验证客户端进行联接尝试时是否连对了位置. 如果实际上没有 postmaster 在那里运行,典型的内核错误是 象上面显示的那样或者是 Connection refused 或者是 No such file or directory. (尤其要注意的是这种环境下 Connection refused的信息显示 并不意味着 postmaster 收到你的联接然后拒绝 了联接--那样的话会产生一个不同的信息,象 Section 4.3里面显示的那样) 其它象 Connection timed out这样的 信息表示更基本的问题,比如缺少网络联接等.
3.4. 运行时配置
有一堆配置参数可以影响数据库系统的行为. 我们在这里描述一下如何设置它们,然后在下一章我们将逐个 讨论它们.
所有参数名都是大小写不敏感的.每个参数都可以接受四种类型之一∶布尔, 整数, 浮点数,字符串.布尔值可以是 ON,OFF, TRUE,FALSE, YES,NO, 1,0 (大小写无关)或这些东西的任意清晰无 歧义的前缀.
设置这些选项的一个方法是在数据目录里比如 (在那里安装着一个缺省文件) 创建一个文件 postgresql.conf 比如,下面是一个该文件的例子:
# This is a comment
log_connections = yes
syslog = 2
象你看到的那样,选项是每条一行.选项名和值之间的等号是可选的. 空白和空行被忽略.井号("#")用做任何地方 引入注释.
每次 postmaster 收到SIGHUP(最简单的发送方法就是 使用 pg_ctl reload). 信号后都会重新读取这个配置文件. postmaster 同时也将这个信号广播给所有正在运行的后端进程这样现有 会话也能得到新的缺省.另外,你可以只向一个后端进程直接发送信号.
第二种设置这些配置参数的方法是把它们作为命令行参数传递给 postmaster, 比如
postmaster -c log_connections=yes -c syslog=2
这样和上面的例子有同样效果. 命令行选项覆盖任何与 postgresql.conf 冲突的选项.
有时候,给某一个特定后端会话一个命令行参数也是很有用的. 可以在客户端使用环境变量 PGOPTIONS 来实现 这个目的:
env PGOPTIONS='-c geqo=off' psql
(这个选项可以用于任何基于libpq的客户端应用,不光是 psql.)请注意,这个变量对那些需要在 服务器启动后固定的选项是无效的,比如端口号.
一些选项可以用 SET 在独立的 SQL 会话中修改, 比如∶
=> SET ENABLE_SEQSCAN TO OFF;
请参考 SQL 命令语言手册获取命令语法的详细信息. 另外,我们可以将一个选项集赋予一个用户或者数据库.在一个会话开始的 时候,为该用户和涉及的数据库装载缺省设置.命令 ALTER DATABASE 和 ALTER USER 分别用于配置这些东西.
3.4.1. pg_settings
虚表 pg_settings 允许显示和更新当前会话的运行时参数。 SHOW ALL 提供的每个可用参数都有一条记录。但是它们出现的 形式是允许它们与其它关系连接并且施加一个选择标准。
一个在 pg_settings 上执行的 UPDATE 等效于在那个命名参数上执行 SET 命令。 这样的修改只影响当前会话使用的数值。如果在一个事务里发出了一个 UPDATE 然后该事务后面退出了,那么 UPDATE 命令的效果在事务 回滚的时候消失。一旦周围的事务提交,那么其效果讲持续到会话结束, 除非被其它 UPDATE 或者 SET 覆盖。