4.PostgreSQL服务管理
服务管理
服务的启停及原理
服务的启停方法
启动数据库实例的方法有以下两种:
- ·直接运行postgres进程启动。
- ·使用pg_ctl命令启动数据库。
1.直接启动数据库的示例如下:
postgres -D /home/osdba/pgdata &
上面的命令中,“-D/home/osdba/pgdata”用于指定数据目录。命令的最后一个“&”表示后台执行。
2.使用pg_ctl命令启动数据库的示例如下:
pg_ctl -D /home/osdba/pgdata start
停止数据库也有两种方法:
·直接向运行的postgres主进程发送signal信号,停止数据库。
·使用pg_ctl命令停止数据库。
停止数据库的模式有以下3种
-
·Smart Shutdown:智能关机模式。在接受此关机请求后,服务器将不允许新连接,等已有的连接全部结束后才关闭数据库。如果服务器处于联机备份模式,它将等到联机备份模式不再活动时才关闭。如果联机备份模式处于活动状态,它将仍然允许超级用户建立新的连接,这是为了允许超级用户连接上来以终止联机备份模式。如果向处于恢复状态的服务器(如Standby数据库)发送智能关机请求,服务器会等待恢复和流复制中的正常会话全部终止后才会停止。这种停库模式用得比较少,因为在这种模式下,用户主动断开数据库连接后数据库才会停止,如果用户一直不断开连接,服务器就无法停止。
-
·Fast Shutdown:快速关闭模式。不再允许新的连接,向所有活跃服务进程发送SIGTERM信号,让它们立刻退出,然后等待所有子进程退出并关闭数据库。如果服务处于在线备份状态,将直接终止备份,这将导致此次备份失败。这种关机模式比较常用。
-
·Immediate Shutdown:立即关闭模式。主进程postgres向所有子进程发送SIGQUIT信号,并且立即退出,所有的子进程也会立即退出。采用这种模式退出时,并不会妥善地关闭数据库系统,下次启动时数据库会重放WAL日志进行恢复,因此建议只在紧急的时候使用该方法。
直接向数据库的主进程发送的signal信号有以下3种。
·SIGTERM:发送此信号为Smart Shutdown关机模式。
·SIGINT:发送此信号为Fast Shutdown关机模式。
·SIGQUIT:发送此信号为Immediate Shutdown关机模式。
pg_ctl命令用不同的命令行参数来表示不同的关机模式,具体如下。
·pg_ctl stop -D DATADIR -m smart:表示Smart Shutdown关机模式。
·pg_ctl stop -D DATADIR -m fast:表示Fast Shutdown关机模式。
·pg_ctl stop -D DATADIR -m immediate:表示Immediate Shutdown关机模式。
pg_ctl工具
pg_ctl是一个实用工具,它具有以下功能:
·初始化PostgreSQL数据库实例。
·启动、终止或重启PostgreSQL数据库服务。
·查看PostgreSQL数据库服务的状态。
·让数据库实例重新读取配置文件。
·允许给一个指定的进程发送信号。
·在Windows平台下允许为数据库实例注册或取消一个系统服务。
- 1.初始化PostgreSQL数据库实例的命令如下:
pg_ctl init[db] [-s] [-D datadir] [-o options]
上面的示例中调用initdb命令创建了一个新的PostgreSQL数据库实例,其参数说明如下。
·-s:只打印错误和警告信息,不打印提示性信息。
·-D datadir:指定数据库实例的数据目录。
·-o options:直接传递给initdb命令的参数,具体可见initdb命令的帮助信息。
eg:$ pg_ctl init -D /home/osdba/pgdata
- 2.启动PostgreSQL数据库的示例如下:
pg_ctl start [-w] [-t seconds] [-s] [-D datadir] [-l filename] [-o options] [-p path] [-c]
其参数说明如下。
·start:启动数据库实例。
·-w:等待启动完成。
·-t:等待启动完成的等待秒数,默认为60秒。
·-s:只打印错误和警告信息,不打印提示性信息。
·-D datadir:指定数据库实例的数据目录。
·-l:把服务器日志输出附加在filename文件上,如果该文件不存在则自动创建。
·-o options:声明要直接传递给postgres的选项,具体可见postgres命令的帮助信息。
·-p path:指定postgres可执行文件的位置。默认postgres可执行文件来自与pg_ctl相同的目录,不必使用该选项,除非进行一些特殊的操作,或者产生postgres执行文件找不到的错误。
·-c:提高服务器的软限制(ulimit -c),尝试允许数据库实例在发生某些异常时产生一个coredump文件,以便进行问题定位和故障分析。
eg:
pg_ctl start -w -D
- 3.停止PostgreSQL数据库的示例如下:
pg_ctl stop [-W] [-t seconds] [-s] [-D datadir] [-ms[mart] | f[ast] | i[mmediate] ]
其参数说明如下。
·-W:不等待数据库停止,就返回命令。
·-m:指定停止的模式。停止的几种模式前面已做介绍,这里不再赘述。
未说明的参数的含义与启动数据库命令中的相应参数含义相同
eg:
pg_ctl stop -D /home/osdba/pgdata -m f
- 4.重启PostgreSQL数据库的示例如下:
pg_ctl restart [-w] [-t seconds] [-s] [-D datadir] [-c] [-m s[mart] | f[ast] | i[mmediate] ] [-o options]
此命令中的参数与启动或停止命令中的相应参数含义相同,这里不再赘述
- 5.让数据库实例重新读取配置文件的命令如下:
pg_ctl reload [-s] [-D datadir]
在配置文件中改变参数后,需要使用上面的命令使参数生效,如修改pg_hba.conf中的配置后就可以使用该命令使之生效。
eg:
pg_ctl reload -D /home/osdba/pgdata
- 6.查询数据库实例状态的命令如下:
pg_ctl status [-D datadir]
eg:
pg_ctl status -D /home/osdba/pgdata
- 7.下面的命令用于给指定的进程发送信号。此命令在Windows平台下(杀会话)
比较有用,因为Windows平台下没有kill命令:
pg_ctl kill [signal_name] [process_id]
下面举例说明。此示例是针对Windows平台下的PostgreSQL数据库的,在使用psql连接到数据库时,运行“select pg_sleep(600)”命令,然后在操作系统的另一个窗口下用“pg_ctl kill”命令中断前一个窗口中正在执行的命令。连接到psql后,执行命令之前先查询该连接对应的后台数据库服务的进程号,命令如下:
postgres=# select pg_backend_pid();
pg_backend_pid
----------------
3900
(1 行记录)
然后在此psql中运行如下命令:
select pg_sleep(600);
再向此后台数据库服务进程发送kill信号,取消上面的SQL命令的执行。运行如下命令:
pg_ctl kill INT 3900
在前面的psql窗口中可以看到如下输出:
postgres=# select pg_sleep(60);
错误: 由于用户请求而正在取消查询
上面的示例说明向进程发送的INT信号把正在执行的SQL命令取消了。
- 8.注册和删除服务
不过,一般都使用函数“pg_cancel_backend(pid int)”来实现上述功能。在Windows平台下注册和取消服务的命令如下
pg_ctl register [-N servicename] [-U username] [-P password] [-D datadir] [-w] [-t seconds] [-o options]
pg_ctl unregister [-N servicename]
删除一个服务的命令如下:
pg_ctl unregister -N postgresql-9.2
增加一个服务的命令如下:
pg_ctl register -D "C:\Program Files\PostgreSQL\9.2\data"
信号
postgres及单用户模式
启动PostgreSQL数据库服务器,实际上就是使用不同的参数运行postgres程序。postgres程序有很多命令行参数,大家可以查看PostgreSQL中的相关内容,此处不再详细介绍postgres程序的使用方法。
本节主要介绍postgres的单用户模式。postgres单用户模式就是启动postgres程序时加上“--single”参数,这时postgres进程不会进入后台服务模式,而是进入交互式的命令行模式下,示例如下:
osdba@osdba-laptop:~$ postgres --single -D /home/osdba/pgdata postgres
PostgreSQL stand-alone backend 9.2.4
backend>
在此交互模式下可以执行一些命令,如一些SQL语句等。
单用户模式主要用于修复数据库的以下几种场景:
·当多用户模式不接收所有命令时,可以使用单用户模式连接到数据库。
·initdb阶段。
·修复系统表。
概念
PostgreSQL 的“单用户模式”(single-user mode)是一种特殊的启动模式,主要用于紧急维护、系统表损坏修复或忘记超级用户密码等极端场景。在这种模式下,数据库集群会以单进程、单用户的方式启动,不监听端口、不接受网络连接,只允许一个本地会话直接访问数据目录。
- 核心特点
- 无认证:不检查用户名/密码(默认以超级用户身份进入)。
- 无并发:禁止其他连接,避免锁竞争。
- 直接访问数据目录:绕过共享内存和锁机制。
- 可执行受限SQL:允许对系统表执行高危操作(如UPDATE pg_authid)。
典型使用场景
| 场景 | 操作示例 |
|---|---|
| 忘记超级用户密码 | ALTER USER postgres PASSWORD 'xxx'; |
| 系统表损坏修复 | REINDEX SYSTEM postgres; |
| 无法启动时的诊断 | 检查pg_class、pg_index等表 |
启动步骤
- 停止正常服务
sudo systemctl stop postgresql # Linux
pg_ctl stop -D /path/to/data # 通用方式
- 进入单用户模式
postgres --single -D /path/to/data postgres
--single:启用单用户模式。
-D /path/to/data:指定数据目录(必需)。
最后的postgres是数据库名称(可替换为其他库名)。
- 执行SQL命令
进入后会看到提示符:
PostgreSQL stand-alone backend 16.3
backend> -- 在此处输入SQL
示例:重置超级用户密码
ALTER USER postgres PASSWORD 'newpassword';
案例:
在PostgreSQL中的一条记录上,事务年龄不能超过231,如果超过该范围,这条数据就会丢失。PostgreSQL数据库不允许这种情况发生,当记录的年龄离231还有1千万的时候,数据库的日志中就会发出如下告警:
WARNING: database "osdba" must be vacuumed within 177000234 transactions
HINT: To avoid a database shutdown, execute a databasewide VACUUM in "osdba".
如果不处理,当记录的年龄离231还有1百万时,出于安全考虑,数据库服务器将自动禁止来自任何用户的连接,同时在日志中提示如下信息:
ERROR: database is not accepting commands to avoid wraparound data loss in database "osdba"
HINT: Stop the postmaster and use a standalone backend to VACUUM in "osdba".
在这种情况下,只能把数据库启动到单用户模式下执行VACUUM命令来修复。
osdba@osdba-laptop:~$ postgres --single -D /home/osdba/pgdata postgres
PostgreSQL stand-alone backend 9.2.4
backend> vacuum full;
backend> Ctrl+D
注意事项
- 备份数据:操作前务必用pg_dumpall或文件系统快照备份。
- 谨慎操作:对系统表(如pg_authid、pg_database)的误操作可能导致数据库无法启动。
- 版本差异:某些旧版本可能需要--single=postgres(等号指定数据库名)。
- 权限要求:需以操作系统用户postgres(或数据目录所有者)身份运行。
服务配置介绍
参数格式和查看
PostgreSQL的配置参数是在postgresql.conf文件中集中管理的,该文件位于数据库实例的目录($PGDATA)下。此文件中的每个参数配置项的格式都是“参数名=参数值”,格式如下面的配置项:
# 这是一个注释
log_connections = yes
log_destination = 'syslog'
search_path = '"$user", public'
shared_buffers = 128MB
配置文件中可以使用“#”进行注释。
所有配置项的参数名都是大小写不敏感的。参数值有以下5种数据类型。
·布尔:布尔值都是大小写无关的,可以是on、off、true、false、yes、no、1、0。
·整数:数值可以指定单位,如一些内存配置的参数可以指定KB、MB、GB等单位。
·浮点数:可以指定小数的数值,如“1.0”。
·字符串:单引号包起来的字符串,如'csvlog'。
·枚举:不需要单引号引起来的字符串。
postgresql.conf文件中还可以使用include指令包含其他文件中的配置内容,示例如下:
include 'filename'
如果指定被包含的文件名不是绝对路径,那么就是相对于当前配置文件所在目录的相对路径。包含还可以被嵌套。
所有的配置参数都在系统视图“pg_settings”中,见下面的例子。
当不知道枚举类型的配置参数“client_min_messages”可以取哪些值时,可用如下语句查询:
select enumvals from pg_settings where name =
'client_min_messages';
当不知道参数“autovacuum_vacuum_cost_delay”的时间单位时,可以使用如下命令查询:
select unit from pg_settings where name =
'autovacuum_vacuum_cost_delay';
关于参数“autovacuum_vacuum_cost_delay”的描述可以使用如下命令查询:
osdba=# select short_desc,extra_desc from pg_settings where name = 'autovacuum_vacuum_cost_delay';
short_desc |
extra_desc
----------------------------------------------------+----------
--
Vacuum cost delay in milliseconds, for autovacuum.|
(1 row)
pg_settings 的字段解析
下面给出 PostgreSQL 系统视图 pg_settings 全部字段 的逐条释义、取值示例及实战提示。字段顺序与官方 17 版手册一致,已结合中文社区常用叫法
| 字段名 | 类型 | 说明与取值示例 |
|---|---|---|
| name | text | 参数名,如 shared_buffers。 |
| setting | text | 当前生效值(字符串形式),如 128MB。 |
| unit | text | 隐式单位,如 MB、ms。若参数无单位则为空。 |
| category | text | 逻辑分组,如 Write-Ahead Log / Settings。便于在 GUIs(pgAdmin、DMS)中折叠显示。 |
| short_desc | text | 一句话说明,如 Sets the number of shared memory buffers used by the server。 |
| extra_desc | text | 更长的解释或注意事项;很多参数为空。 |
| context | text | 决定“怎么改、何时生效”。按“修改难度”从高到低:internal → 只读,重建集群才能变;postmaster → 需重启;sighup → 重载(pg_reload_conf())即可全局生效;superuser-backend → 重载后对新连接生效,且仅超级用户可在会话级 SET;backend → 同上,但普通用户也可 SET;superuser → 可随时 SET,仅超户;user → 任何用户都可 SET 会话级。 |
| vartype | text | 数据类型:bool、enum、integer、real、string。 |
| source | text | 当前值的来源:default、override、configuration file、command line、database、session、environment variable 等。 |
| min_val | text | 最小允许值(数值型才有),如 32。 |
| max_val | text | 最大允许值(数值型才有),如 2147483647。 |
| enumvals | text[] | 仅对 vartype = enum 非空,列出合法取值,如 {"read write","read only"}。 |
| boot_val | text | 服务器启动时的缺省值,如 1024。 |
| reset_val | text | 当前会话执行 RESET 后会被设回的值(来自配置文件或默认)。 |
| sourcefile | text | 该值所在的配置文件路径;若非文件来源(如 ALTER SYSTEM、默认)则为 NULL。 |
| sourceline | integer | 在上述文件中的行号;同样可为 NULL。 |
| pending_restart | boolean | 如果配置文件中已修改但尚未重启则为 true;运维脚本常用它批量检查“是否需要重启”。 |
context 的生效规则
internal ─┬─ 完全只读
postmaster ─┼─ 改配置 → 重启
sighup ─┼─ 改配置 → reload (pg_ctl reload -D /home/osdba/pgdata)
superuser/backend─┼─ 改配置 → reload 仅对新会话;会话内 SET 立即生效
superuser/user ─┴─ 会话级 SET 立即生效;配置文件 reload 仅影响未 SET 的会话
典型查询示例
-- 1. 查看需要重启的参数
SELECT name, setting, pending_restart
FROM pg_settings
WHERE pending_restart;
-- 2. 查看所有内存相关参数(逻辑分组)
SELECT name, setting, unit, context
FROM pg_settings
WHERE category LIKE '%Memory%';
-- 3. 找到数值型参数的范围
SELECT name, min_val, max_val, boot_val
FROM pg_settings
WHERE vartype IN ('integer','real');
参数分类
参数的访问和设置也有多种情况,有些参数发生改变后必须重启服务器才能生效,有些参数可以直接修改,还有一些参数只有超级用户才有权限修改。在PostsgreSQL中把参数分为以下几类。
·internal:这类参数是只读参数,其中,有些参数是postgres程序写死的,或者是用不同的编辑选项确定的;有些参数是数据库实例初使化时就确定了的,比如创建实例时运行initdb,可以使用一些命令行参数选项来确定某些参数的值,如可以在initdb中使用-k把参数“data_checksums”初使化为“on”,之后就不能再改变此参数值了。这类参数值不能在postgresql.conf中配置,因为它们是由postgres程序或在初始化实例时写死的。
·postmaster:改变这类参数的值需要重启PostgreSQL实例。在postgresql.onf文件中可改变这些参数后,需要重启PostgreSQL实例修改才能生效。
·sighup:在postgresql.conf文件中改变这类参数的值不需要重启数据库,只需要向postmaster进程发送SIGHUP信号,让其重启装载配置新的参数值就可以了。当然postmaster进程接收到SIGHUP信号后,也会向它的子进程发送SIGHUP信号,让新的参数值在所有的进程中生效。
·backend:在postgresql.conf文件中更改这类设置无须重新启动服务器,只需要向postmaster发送一个SIGHUP信号,让它重新读取postgresql.conf文件中新的配置值,但新的配置值只会出现在修改之后的新连接中,已有的连接中该参数的值不会改变。这类参数的值也可以在新建连接时由连接的一些参数改变。例如,通过libpq的PGOPTIONS环境变量可以改变本连接的配置值。
·superuser:这类参数可以由超级用户使用SET命令来改变,如检测死锁的超时时间的参数“deadlock_timeout”。而超级用户改变此参数值时只会影响自身的sesssion配置,不会影响其他用户关于此参数的配置。向
Postmaster进程发送SIGHUP信号也只会影响后续创建的连接,不会影响已有的连接。
·user:这类参数可以由普通用户使用SET命令来改变本连接中的配置值。除了普通用户也可以改变外,这类参数与superuser类参数没有区别。
可以通过查询pg_settings表中的context字段值来了解改变参数在postgresql.conf文件中的配置值时,是否需要重启数据库,示例如下。
连接配置项
本节主要介绍连接数据库相关的配置项,这些配置项有以下几种。
-
·listen_addresses:string类型,声明服务器监听客户端连接的TCP/IP地址,改变此参数需要重启数据库服务。
如果主机有多个IP地址,则让PostgreSQL服务在多个IP地址上监听,该参数的配置值就是由逗号分隔的多个IP地址值或IP地址值对应的主机名组成的一个列表。通常把此项配置为“”,表示在本机的所有IP地址上监听。当然也可以配置成“0.0.0.0”,它与“”相同,也表示在本机所有的IP地址上监听。
如果这个列表是空的,那么服务器不会监听任何IP地址,在这种情况下,只有UNIX域套接字可以连接到数据库。此参数的默认值是“localhost”,表示只允许本地使用“loopback”连接到数据库,其他机器无法连接。更精细的控制项,如哪些IP或哪些网段可以连接服务器,是由配置文件“pg_hba.conf”来控制的。当然,listen_addresses也可以控制只在一个特定的IP地址上监听,所以可以有针对性地阻止不安全网卡的恶意连接请求。 -
·port:integer类型,指定服务器监听的TCP端口,默认为“5432”。改变该参数需要重启数据库服务。请注意,同一个端口号用于服务器监听的所有IP地址。
-
·max_connections:integer类型,允许与数据库连接的最大并发连接数。改变该参数需要重启数据库服务。默认值通是“100”,但是如果内核设置不支持(在initdb时判断),该值可能会小于这个数。这个参数只能在服务器启动的时候设置。增大该参数可能会让PostgreSQL申请更多的System V共享内存或信号灯,可能会因超过操作系统默认配置值而导致实例无法启动。当运行HOT Standby服务器时,该参数必须大于或等于主服务器上的参数,否则HOT Standby服务器上可能无法执行查询操作。
-
·superuser_reserved_connections:integer类型,决定为PostgreSQL超级用户连接而保留的连接数。改变该参数需要重启数据库服务。默认值是“3”。设置该参数的目的在于防止因普通用户消耗掉允许的所有连接而导致超级用户无法连接到数据库。普通用户最多建max_connections-superuser_reserved_connections个连接后就不再允许连接数据库了,这时超级用户还可以连接到数据库。该值必须小于max_connections的值。
-
·unix_socket_directory:string类型,明服务器监听客户端连接的UNIX域套接字目录声。该参数只能在编译时修改。默认值通常是
“/tmp”。除了套接字文件本身,名为“.s.PGSQL.nnnn”“.s.PGSQL.nnnn.lock”(nnnn是服务器的端口号)的文件会在unix_socket_directory路径下创建,这两个文件都不应被手动删除。Windows下没有UNIX域套接字,因此该参数与Windows无关。 -
·unix_socket_group:string类型,设置UNIX域套接字的所属组(套接字的所属用户总是启动服务器的用户)。改变该参数需要重启数据库服务。可以与选项“unix_socket_permissions”一起用于对套接字进行访问控制。默认是一个空字符串,表示启动服务器的用户所属的默认组。该选项只能在服务器启动时设置。Windows下没有UNIX域套接字,因此该参数与Windows无关。
-
·unix_socket_permissions:integer类型,设置UNIX域套接字的访问权限。改变该参数需要重启数据库服务。UNIX域套接字文档的权限与普通的UNIX文件系统权限相同,该选项的值应该是数值形式,也就是chmod函数和umask函数中接受的形式。如果使用八进制格式,数字必须以0开头。默认的权限是“0777”,意思是任何用户都可以连接。通常合理的设置也可能是“0770”(只有用户和同组的用户可以访问)和“0700”(只有用户自己可以访问)。需要注意的是,对于UNIX域套接字,只有写权限有意义,读和执行权限没有任何意义。Windows下没有UNIX域套接字,因此该参数与Windows无关。
-
·bonjour:boolean类型,Bonjour也称为零配置联网,是苹果电脑公司的一个服务器搜索协议,此参数表示是否让Bonjour搜索到
PostgreSQL服务。改变该参数需要重启数据库服务。默认值是“off”。 -
·bonjour_name:string类型,声明Bonjour服务名称。改变该参数需要重启数据库服务。默认值为空字符串,表示使用本机名。如果编译时没有打开Bonjour支持,那么将忽略该参数。
-
·tcp_keepalives_idle:integer类型,表示在一个TCP连接中空闲多长时间后会发送一个keepalive报文。默认值为“0”,表示使用操作系统设置的默认值,因为Windows不支持读取系统默认值,在Windows操作系统上此值若设置为“0”,系统会将该参数设置为2小时。该参数只有在支持TCP_KEEPIDLE或TCP_KEEPALIVE功能的操作系统上才可用,如Windows和Linux。在不支持此功能的操作系统上必须设置为“0”。此参数只对TCP连接有用,UNIX域套接连接会忽略该参数。
-
·tcp_keepalives_interval:integer类型,在一个空闲TCP连接中,定义在发送第一个TCP keepalive包后,如果在该参数给定的时间间隔内没有收到对端的回包,则开始发送第二个TCP keepalive包,若在给定的时间间隔内仍未收到回包的话则发送第三个keepalive包,直到达到tcp_keepalives_count次后都没有收到回包,则认为连接已中断,关闭连接。若指定为“0”,即表示使用操作系统设置的默认值,但在Windows操作系统上,因为Windows不支持读取系统默认值,此值若设置为“0”,系统会将该参数设置为1秒。该参数只有在支持TCP_KEEPIDLE或TCP_KEEPALIVE功能的操作系统上才可用,如Windows和Linux。在不支持此功能的操作系统上,必须设置为“0”。此参数只对TCP连接有用,UNIX域套接连接会忽略该参数。
-
·tcp_keepalives_count:integer类型,在一个空闲TCP连接上,发送keepalive包后,如果一直没有收到对端的回包,最多发送keepalive次报文后就认为TCP连接已中断。若指定为“0”,即表示使用操作系统设置的默认值。该参数只有在支持TCP_KEEPCNT功能的操作系统上才可用,在不支持此功能的操作系统上,必须设置为“0”。Windows操作系统也不支持此参数,所以也必须设置为“0”。此参数只对TCP连接有用,UNIX域套接连接会忽略该参数。
在上面的参数中,需要注意的是TCP的keepalive参数的设置,在Linux环境下,通常要把tcp_keepalives_idle设置为较短的时间值。默认设置为“0”时,使用操作系统的设置值,通常为7200秒,即2小时,这个时间间隔对于大多数应用来说都太长了,所以需要设置为较短的时间值,如下面的配置:
tcp_keepalives_idle = 180
tcp_keepalives_interval = 10
tcp_keepalives_count = 3
内存配置项
对于任何数据库软件来说,内存配置项都是很重要的配置项。在PostgreSQL中主要有以下几个内存配置参数。
-
·shared_buffers:integer类型,设置数据库服务器将使用的共享内存缓冲区数量,此缓冲区为数据块的缓存使用。此缓冲区是放在共享内存中的。每个缓冲区大小的典型值是8KB,除非在编译时修改了BLCKSZ的值。默认值通常是“4000”,对于8KB的数据块则共享内存缓冲区大小为4000×8KB≈32MB。这个数值必须大于16,并且至少是max_connections数值的两倍。通常会把此值设置得大一些,这样可以改进性能。在安装生产系统时,建议至少将该值设置为几千。如果有专用的1GB或更多内存的数据库服务器,一个合理的shared_buffers开始值可以是物理内存的25%。
-
但把shared_buffers设置得太大,如超过物理内存的40%后,就会发现缓存的效果并不明显,这是因为PostgreSQL是运行在文件系统之上的,若文件系统也有缓存,将导致双缓存过多,产生负面影响。通常情况下,将share_buffers设置为物理内存的25%,而把更多的内存留给文件系统的缓存。在Windows环境下也是如此。在早期的PostgreSQL版本下,增大该参数的值可能会要求更多System V共享内存,可能会超出操作系统共享内存配置参数允许的大小。
-
·temp_buffers:integer类型,设置每个数据库会话使用的临时缓冲区的最大数目。此本地缓冲区只用于访问临时表。临时缓冲区是在某个连接会话的服务进程中分配的,属于本地内存。临时缓冲区的大小也是按数据块大小来分配的,默认值是“1000”,对于8KB的数据块大小为8MB。每个会话可以使用SET命令改变此设置值,但是必须在会话第一次使用临时表前设置才有效,一旦使用了临时表,再改变该数值将是无效的。并不是一启动会话就分配这么多临时缓冲区的内存,而是按需分配,在需要时才分配实际的临时缓冲区内存。如果在一个并不需要大量临时缓冲区的会话里设置一个较大的数值,它的开销只是一个缓冲区描述符,每个BLOCK就会增加大约64B的内存用于存储缓冲区描述符。
-
·work_mem:integer类型,声明内部排序操作和Hash表在开始使用临时磁盘文件之前使用的内存数目。这个内存也是本地内存,以千字节为单位,默认是1024 KB(1MB)。请注意,对于复杂的查询,可能会同时并发运行多个排序或散列(Hash)操作;每个排序或散列操作都会分配该参数声明的内存来存储中间数据,只有存不下时才会使用临时文件。同样,多个正在运行的会话可能会同时进行排序操作,因此使用的总内存可能是work_mem的好几倍。ORDER BY、DISTINCT和MERGE JOINS都要用到排序操作。Hash表在Hash Join、以Hash为基础的聚集、以Hash为基础的IN子查询处理中也都要用到排序。
-
·maintenance_work_mem:integer类型,声明在维护性操作,比如VACUUM、CREATE INDEX和ALTER TABLE ADD FOREIGN KEY中使用的最大内存数以KB为单位,默认是16MB。在一个数据库会话里,只有这样的操作可以执行,并且一个数据库实例通常不会有太多这样的工作并发执行,通常把该数值设置得比work_mem大一些较为合适。更大的设置可以提高上述操作的执行效率。配置AutoVacuum后,达到autovacuum_max_workers的时间,内存会被分配,因此也不要将默认值设置得太大,而当需要手动执行上述操作时,可以使用SET命令把此参数值设置得大一些。
-
·max_stack_depth:integer类型,声明服务器的执行堆栈的最大安全深度。此设置默认为2MB,如果发现不能运行复杂的函数时,可以
适当提高此配置的值,不过通常情况下保持默认值就足够了。
把max_stack_depth参数设置得大于实际的操作系统内核限制值时,意味着一个正在运行的递归函数可能会导致PostgreSQL后台服务进程崩溃。在一些操作系统平台上,PostgreSQL能够检测出内核限制,这时PostgreSQL将不允许其设置为一个不安全的值。但PostgreSQL并不能在所有的操作系统平台上都能检测出操作系统的内核限制值,所以建议还是设置一个明确的值。
预写式日志的配置项
- 1)wal_level:enum类型,可以选择的值为“minimal”“replica”“logical”,此配置项决定了多少信息写入WAL日志中。
改变该参数需要重启数据库服务。
默认值是“minimal”,即只写入在数据库崩溃或突然关机后进行恢复时所需要的信息。
设置为“replica”,则会添加一些备库只读查询时需要的信息。
当执行“CREATE TABLE AS”“CREATE INDEX”“CLUSTER”和“COPY into tables”等批量操作时,如果wal_level设置为“minimal”,那么批量操作只会产生很少的WAL日志,原因是这些批量操作的具体过程可以安全地跳过,并不会影响数据库的恢复,但“minimal”级别的WAL不包括所有从基础备份和WAL日志中重建数据的信息。如果要搭建物理备库,需要把此参数设为“replica”;如果需要使用逻辑同步,需要把此参数设置为“logical”。
-
2)fsync:boolean类型,即是否使用fsync()系统调用(或等价调用)把文件系统中的脏页刷新到物理磁盘,确保数据库能在操作系统或者硬件崩溃的情况下恢复到一致的状态。改变该参数需要重新装载配置文件。此参数默认值为“on”,大多数情况下都应该把这个参数设置为“on”。但当此数据库不是很重要,或者此数据库中的数据很容易在其他系统中重建时,为了提高性能,可以把此参数设置为“off”。例如,从备份文件中初始加载一个新数据库时,可以把此参数设置为“off”,这样可以提升重建的速度。如果这个选项被关闭,那么可以考虑关闭full_page_writes,因为把fsync设置为“off”后,把full_page_writes设置为“on”也无法保证数据的安全性,不如索性全部设置为“off”。
-
3)synchronous_commit:boolean类型,声明提交一个事务是否需要等待其把WAL日志写入磁盘后才返回,默认值是“on”。为了事务的安全,通常都应当设置为“on”。不同于fsync,将此参数设置为“off”不会产生数据库不一致性的风险,只会导致用户已提交成功的最近的几个事务丢失,即在数据库崩溃或突然关机后,重启数据库时用户会发现故障时间点附近的几个事务实际上并没有提交成功,而是回滚了,而数据库状态是一致的。一般用户可以直接改变此参数值,因此在提交一些不重要的事务时,可以先把此参数设置为“off”,然后再提交,这样就可以提高数据库性能。
-
4)wal_sync_method:enum类型,用来指定向磁盘强制更新WAL日志数据的方法。一般保持默认值就可以了。如果fsync设置为
“off”,那么该参数的设置就没有意义。该参数的可选项有以下几种。
·open_datasync:使用O_DSYNC选项的open()函数打开WAL日志,Linux操作系统不支持此选项。Windows下默认使用此选项。
·fdatasync:每次提交时调用fdatasync函数。Linux操作系统上默认使用此选项。
fsync_writethrough:每次提交时调用fsync()函数,同时把所有Cache都刷新到物理硬盘中。Linux操作系统不支持此选项。Windows下支持此选项。
·fsync:每次提交时调用fsync()函数。大多数平台都支持此选项。
·open_sync:使用O_SYNC选项的open()函数来打开WAL日志。大多数平台都支持此选项。
- 5)full_page_writes:boolean类型。打开该选项时,PostgreSQL服务器会在检查点(checkpoints)之后对页面进行第一次修改时将整个页面写到WAL日志中。
这样做是因为在操作系统崩溃过程中可能只有部分页面写入磁盘了,从而导致在同一个页面中会有新旧数据混合的情况。在崩溃后的恢复期,如果WAL日志中没有记录完整的页,且页中的数据是新旧混合的,则无法完全恢复该页。把完整的页面保存在WAL日志中就可以直接使用WAL日志中的页覆盖坏页(包含新旧混合的数据)以完成恢复工作。此参数的默认值为“on”,为了数据安全,通常使用该默认设置。
注意:运行到检查点时,若页面第一次被修改,则整个页面会被写入WAL日志中,但在下一个检查点到来之后该页面若再发生变化,将不会再记录整个页面。也就是说,在两个检查点之间,不管这个页面变化了多少次,只在第一次变化时记录整个页面到WAL日志中,后面
的就不会再记录了。所以,增加检查点产生的时间间隔就能减少WAL的日志量。
-
6)wal_buffers:integer类型,指定放在共享内存中用于存储WAL日志的缓冲区的数目。默认值为“8”,即64KB。改变此参数需要重启数据库服务。此参数设置值的大小只需要能够保存一次事务生成的WAL数据即可,这些数据在每次事务提交时都会写入磁盘。通常此参数设置为8128(64KB1MB)。
-
7)wal_writer_delay:integer类型,指定wal writer process把WAL日志写入磁盘的周期。在每个周期中会把缓存中的WAL日志刷新到磁盘上,休眠wal_writer_delay时间,然后重复上述过程。默认时间为200毫秒。当把synchronous_commit参数设置为“on”时,实际上在每次事务提交时都会把缓存中的WAL日志刷新到磁盘上,因此该参数
通常在synchronous_commit参数设置为“off”时比较有用。当
synchronous_commit参数设置为“off”时,wal_writer_delay参数的
值决定了数据库实例、操作系统或硬件崩溃时,最多丢失多长时间内
已提交事务的数据。 -
8)commit_delay:integer类型,指定向WAL缓冲区写入记录和将缓冲区刷新到磁盘上之间的时间延迟,以微秒为单位。非零的设置值允许多个事务共用一个fsync()系统调用刷新数据。如果系统负载足够高,那么在给出的时间间隔里,其他事务可能已经准备好提交了。但是如果没有其他事务准备提交,那么该延迟就是在浪费时间。因此,该延迟只在一个服务器进程写其提交日志时,且至少commit_siblings个其他事务处于活跃状态的情况下执行。默认是“0”(无延迟)。
9)commit_siblin gs:integer类型,在执行commit_delay延迟时要求同时打开的最小并发事务数。默认是“5”。
错误报告和日志项
日志相关的配置项
·log_destination:前面讲过,可以设置为“stderr”“csvlog”和“syslog”。
·logging_collector:可以设置为“on”或“off”。
·log_directory:日志输出的路径,可以是绝对路径或数据目录的相对路径。
·log_filename:文件名,可以带上格式字符串。
·log_rotation_age:日志超过多长时间后就生成一个新的文件。
·log_rotation_size:日志超过多大时就生成一个新的文件。
·log_truncate_on_rotation:当生成的新文件的文件名已经存在时,是否覆盖同名旧文件。
·syslog_facility:该参数是设置了log_destination='syslog'后,指定syslog的“facility”项。可以设置为LOCAL0、LOCAL1、LOCAL2、LOCAL3、LOCAL4、LOCAL5、LOCAL6、LOCAL7中的一个值。
·syslog_ident:当使用syslog时,用于在syslog日志中标识PostgreSQL的程序名。默认为“postgresql.conf”。
常用配置
通常在刚安装完成的PostgreSQL中,只需对打开日志项进行如下设置,其他项保持默认值,就可以满足用户的大多数要求:
logging_collector = on
采用上述配置后,基本上每天超过10MB大小时会生成一个日志文件,因为即使没有设置,也相当于默认设置了以下两个参数:
log_rotation_age = 1d
log_rotation_size = 10MB
每次重启数据库时也会生成一个新的日志文件。
在这种方式下,PostgreSQL并不会自动清理日志文件,需要写一个脚本程序来清理日志文件。
实际上,PostgreSQL数据库也可以把日志发送到操作系统的syslog中,或者多生成一个csv格式的日志,此操作通过配置log_destination参数来完成。如下配置就是把日志发送到syslog中:
log_destination = 'syslog'
如果是在Windows操作系统中,把日志发送到Windows的事件日志中的配置方法如下
log_destination = 'eventlog'
如果想要生成一个csv格式的日志文件,需要进行如下配置:
logging_collector = on
log_destination = 'csvlog'
要生成csvlog,需要打开“logging_collector”,如果在syslog和eventlog中生成日志,则不需要打开“logging_collector”。
还有一种常用的日志方法是将PostgreSQL数据库配置成保留固定数目的日志,如保留一周的日志,到了星期一,则把上星期一的日志
覆盖掉,配置方法如下:
log_filename = 'postgresql-%u.log'
log_rotation_age = 1d
log_truncate_on_rotation = on
日志文件名只能是“postgresql-%u.log'”,其中“%u”代表星期几,星期一到星期日对应的值是1~7,将log_truncate_on_rotation
设置为“on”,就会覆盖上周的日志文件,以此来保证只保留7天的日志文件,示例如下:
注意:如果今天是星期三,postgresql-3.log是今天的文件,而postgresql-4.log则是上星期四的文件。这与Linux操作系统中的syslog日志文件是不一样的,在syslog日志中,“syslog”是当前的日志文件,而
“syslog.1”是前一段时间的日志文件,“syslog.2”则是更早一段时间的日志文件,也就是说,“syslog.N”中“N”(值为1,2,3,…)的数值越大表示时间越早的日志文件。而本示例中,这个数据仅代表星期几。在PostgreSQL数据库中,日志文件无法配置成如Linux中的syslog那种保持固定数目的方式。
设置log的级别
PostgreSQL数据库也可以设置log的级别,log的级别控制着记录日志的多少,而log的级别由参数“log_min_messages”来控制,可以取值为:DEBUG5、DEBUG4、DEBUG3、DEBUG2、DEBUG1、INFO、NOTICE、WARNING、ERROR、LOG、FATAL、PANIC,级别排序越靠后,则打印到日志文件中的内容就越少。
| 级别关键字 | 含义 / 触发场景 | 备注 |
|---|---|---|
| PANIC | 导致整个数据库集群强制关闭的错误 | 极少出现,如共享内存损坏 |
| FATAL | 导致当前会话终止的错误 | 例如连接被管理员 pg_terminate_backend |
| LOG | 服务器级普通信息 | 例如 checkpoint 完成 |
| ERROR | SQL 语句级错误(事务仍在) | 例如违反约束 |
| WARNING | 潜在问题,但语句执行成功 | 例如 TRUNCATE 触发器被忽略 默认值 |
| NOTICE | 普通提示 | 例如 VACUUM 跳过空页 |
| INFO | 额外信息 | 很少用,由扩展或插件打印 |
| DEBUG1 … DEBUG5 | 调试信息 | 仅在编译时打开 DEBUG 才有效 |
如何设置
1.写到日志文件的最低级别
log_min_messages = warning # postgresql.conf 全局
ALTER SYSTEM SET log_min_messages = 'warning'; -- 或 SQL 级
2.记录导致错误的 SQL 语句
log_min_error_statement = error # 仅当语句产生 ERROR 及以上时才记录
慢日志设置
PostgreSQL也有类似MySQL中的慢查日志功能,也就是把一些运行慢的SQL语句记录到日志中,在PostgreSQL中该功能是由参数“log_min_duration_statement”来控制的,如果某个SQL语句的运行时间大于或等于设定的毫秒数,那么该SQL语句和它运行的时间就会被记录到日志中。当设置为“0”时,则所有运行的SQL语句及其时间都会被记录到日志文件中。
慢日志参数配置:
以下是一份可直接落地的「PostgreSQL 慢查询日志参数配置清单」:(示例阈值:≥500 ms,保存 30 天,按日切割)
修改 postgresql.conf(或 ALTER SYSTEM)
# ---------- 基础日志 ----------
logging_collector = on # 写日志文件
log_destination = 'stderr' # 或 csvlog
log_directory = 'log' # $PGDATA/log
log_filename = 'slow_%Y-%m-%d.log' # 每天 00:00 切
log_rotation_age = 1d
log_rotation_size = 100MB # 单日过大也切
log_truncate_on_rotation = on # 同名截断
# ---------- 慢查询 ----------
log_min_duration_statement = 500 # 500 ms 及以上
# 若想同时记录所有 SQL 的耗时,可加:
log_duration = off # 避免冗余
log_statement = 'none' # 不额外全量记录
# ---------- 让日志更易读 ----------
log_line_prefix = '%t [%p-%l] %u@%d %a %h %v ' # 时间、用户、数据库、应用、IP、虚拟事务
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0 # 记录 >0 B 的临时文件
生效
SELECT pg_reload_conf(); -- 无需重启
验证
SELECT pg_sleep(0.6); -- 立即生成 600 ms 记录
保留 30 天
PostgreSQL 不会自动删旧文件,推荐 logrotate:
# /etc/logrotate.d/postgresql-slow
/pgdata/16/main/log/slow_*.log {
daily
missingok
rotate 30 # 保留 30 份
compress
delaycompress
copytruncate
}

浙公网安备 33010602011771号