19.8. 错误报告和日志

19.8.1. 在哪里做日志

log_destination (string)

PostgreSQL支持多种方法来记录服务器消息,包括stderrcsvlogsyslog。在 Windows 上还支持eventlog。设置这个参数为一个由想要的日志目的地的列表,之间用逗号分隔。默认值是只记录到stderr。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

如果csvlog被包括在log_destination中,日志项会以"逗号分隔值"CSV)格式被输出,这样可以很方便地把日志载入到程序中。详见第 19.8.4 节。要产生 CSV 格式的日志输出,必须启用logging_collector

注意: 在大多数 Unix 系统上,你将需要修改系统的syslog守护进程的配置来使用log_destinationsyslog选项。PostgreSQL可以在syslog设备LOCAL0LOCAL7中记录(见syslog_facility),但是大部分平台上的默认syslog配置会丢弃所有这种消息。你将需要增加这样的内容:

local0.*    /var/log/postgresql

syslog守护进程的配置文件来让它工作。

在 Windows 上,当你使用log_destinationeventlog选项时,你应该在操作系统中注册一个事件源及其库,这样 Windows 事件查看器能够清楚地显示事件日志消息。详见第 18.11 节

logging_collector (boolean)

这个参数启用日志收集器,它是一个捕捉被发送到stderr的日志消息的后台进程,并且它会将这些消息重定向到日志文件中。这种方法比记录到syslog通常更有用,因为某些类型的消息不会在syslog输出中出现(一个常见的例子是动态链接器错误消息;另一个例子是由archive_command等脚本产生的错误消息)。这个参数只能在服务器启动时设置。

注意: 也可以不使用日志收集器而把日志记录到stderr,日志消息将只会去到服务器的stderr被定向到的位置。不过,那种方法只适合于低日志量,因为它没有提供方法来轮转日志文件。还有,在某些不使用日志收集器的平台上可能会导致丢失或者混淆日志输出,因为多个进程并发写入同一个日志文件时会覆盖彼此的输出。

注意: 日志收集器被设计成从来不会丢失消息。这意味着在极高的负载下,如果服务器进程试图在收集器已经落后时发送更多的日志消息,那么它会被阻塞。相反,syslog倾向于在无法写入消息时丢掉消息,这意味着在这样的情况下它可能会无法记录某些消息,但是它不会阻塞系统的其他部分。

log_directory (string)

logging_collector被启用时,这个参数决定日志文件将被在哪个目录下创建。它可以被指定为一个绝对路径,也可以被指定为一个相对于集簇数据目录的相对路径。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。 默认是pg_log

log_filename (string)

logging_collector被启用时,这个参数设置被创建的日志文件的文件名。该值被视为一种strftime模式,因此%转义可以被用来指定根据时间变化的文件名(注意如果有任何时区独立的%转义,计算将在由log_timezone指定的时区中完成)。被支持的%转义和开放组织的strftime说明中列举的类似。 注意系统的strftime不会被直接使用,因此平台相关(非标准)的扩展无法工作。 默认是postgresql-%Y-%m-%d_%H%M%S.log

如果你不使用转义来指定一个文件名,你应该计划使用一个日志轮转工具来避免最终填满整个磁盘。在 8.4 发行之前,如果不存在%转义,PostgreSQL将追加新日志文件创建时间的纪元,但是现在已经不再这样做了。

如果在log_destination中启用了 CSV 格式输出,.csv将会被追加到时间戳日志文件名中来创建 CSV 格式输出(如果log_filename.log结尾,该后缀会被替换)。

这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

log_file_mode (integer)

在 Unix 系统上,当logging_collector被启用时,这个参数设置日志文件的权限(在微软 Windows 上这个参数将被忽略)。这个参数值应当是一个数字形式的模式,它可以被chmodumask系统调用接受(要使用通常的十进制格式,该数字必须以一个0(零)开始)。

默认的权限是0600,表示只有服务器拥有者才能读取或写入日志文件。其他常用的设置是0640,它允许拥有者的组成员读取文件。不过要注意你需要修改log_directory为将文件存储在集簇数据目录之外的某个位置,才能利用这个设置。在任何情况下,让日志文件变成任何人都可读是不明智的,因为日志文件中可能包含敏感数据。

这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

log_rotation_age (integer)

logging_collector被启用时,这个参数决定一个个体日志文件的最长生命期。当这些分钟过去后,一个新的日志文件将被创建。将这个参数设置为零将禁用基于时间的新日志文件创建。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

log_rotation_size (integer)

logging_collector被启用时,这个参数决定一个个体日志文件的最大尺寸。当这么多千字节被发送到一个日志文件后,将创建一个新的日志文件。将这个参数设置为零将禁用基于尺寸的新日志文件创建。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

log_truncate_on_rotation (boolean)

logging_collector被启用时,这个参数将导致PostgreSQL截断(覆盖而不是追加)任何已有的同名日志文件。不过,截断只在一个新文件由于基于时间的轮转被打开时发生,在服务器启动或基于尺寸的轮转时不会发生。如果被关闭,在所有情况下以前存在的文件将被追加。例如,使用这个设置和一个类似postgresql-%H.loglog_filename将导致产生 24 个每小时的日志文件,并且循环地覆盖它们。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

例子:要保留 7 天的日志,每天的一个日志文件被命令为server_log.Monserver_log.Tue等等,并且自动用本周的日志覆盖上一周的日志。可以这样做:将log_filename设置为server_log.%a、将log_truncate_on_rotation设置为on并且将log_rotation_age设置为1440

例子:要保留 24 小时的日志,每个小时一个日志文件,但是在日志文件尺寸超过 1GB 时轮转。可以这样做:将log_filename设置为server_log.%H%M、 将log_truncate_on_rotation设置为on、 将log_rotation_age设置为60并且 将log_rotation_size设置为1000000。 Including %M in 在log_filename中包括%M允许发生任何尺寸驱动的轮转来选择一个不同于每个小时的初始文件名的新文件名。

syslog_facility (enum)

当启用了向syslog记录时,这个参数决定要使用的syslog"设备"。你可以在LOCAL0LOCAL1LOCAL2LOCAL3LOCAL4LOCAL5LOCAL6LOCAL7中选择,默认值是LOCAL0。还请参阅系统的syslog守护进程的文档。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

syslog_ident (string)

当启用了向syslog记录时,这个参数决定用来标识syslog中的PostgreSQL消息的程序名。默认值是postgres。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

syslog_sequence_numbers (boolean)

当日志被记录到syslog并且这个设置为 on (默认)时,每一个消息会被加上一个增长的序号作为前缀(例如 [2])。这种行为避开了很多 syslog 实现默认采用的 "--- 上一个消息重复 N 次 ---"形式。在现代 syslog 实现中, 抑制重复消息是可以配置的(例如rsyslog 中的$RepeatedMsgReduction),因此这个参数可能不是必需的。 此外,如果你真的想抑制重复消息,你可以把这个参数设置为 off。

这个参数只能在postgresql.conf文件或者服务器命令行上设置。

syslog_split_messages (boolean)

当启用把日志记录到syslog时,这个参数决定消息如何送达 syslog。当设置为 on(默认)时,消息会被分成行, 并且长的行也会被划分以便能够放到 1024 字节中, 这是传统 syslog 实现一种典型的尺寸限制。当设置为 off 时, PostgreSQL 服务器日志消息会被原样送达 syslog 服务, 而处理可能的大体量消息的任务由 syslog 服务负责。

如果 syslog 最终被记录到一个文本文件中,那么两种设置的效果是一样的, 但最好设置为 on,因为大部分 syslog 实现要么不能处理大型消息, 要么需要做特殊的配置以处理大型消息。但是如果 syslog 最终写入到某种其他媒介,有必要让消息保持逻辑上的整体性(也更加有用)。

这个参数只能在postgresql.conf文件或者服务器命令行上设置。

event_source (string)

当启用了向事件日志记录时,这个参数决定用来标识日志中PostgreSQL消息的程序名。默认值是PostgreSQL。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

19.8.2. 什么时候记录日志

client_min_messages (enum)

控制被发送给客户端的消息级别。有效值是DEBUG5DEBUG4DEBUG3DEBUG2DEBUG1LOGNOTICEWARNINGERRORFATALPANIC。每个级别都包括其后的所有级别。级别越靠后,被发送的消息越少。默认值是NOTICE。注意LOG在这里有与log_min_messages中不同的排名。

log_min_messages (enum)

控制哪些消息级别被写入到服务器日志。有效值是DEBUG5DEBUG4DEBUG3DEBUG2DEBUG1INFONOTICEWARNINGERRORLOGFATALPANIC。每个级别都包括以后的所有级别。级别越靠后,被发送的消息越少。默认值是WARNING。注意LOG在这里有与log_min_messages中不同的排名。只有超级用户可以改变这个设置。

log_min_error_statement (enum)

控制哪些导致一个错误情况的 SQL 语句被记录在服务器日志中。任何指定严重级别或更高级别的消息的当前 SQL 语句将被包括在日志项中。有效值是DEBUG5DEBUG4DEBUG3DEBUG2DEBUG1INFONOTICEWARNINGERRORLOGFATALPANIC。默认值是ERROR,它表示导致错误、日志消息、致命错误或恐慌错误的语句将被记录在日志中。要有效地关闭记录失败语句,将这个参数设置为PANIC。只有超级用户可以改变这个设置。

log_min_duration_statement (integer)

如果语句运行至少指定的毫秒数,将导致记录每一个这种完成的语句的持续时间。将这个参数设置为零将打印所有语句的执行时间。设置为 -1 (默认值)将停止记录语句持续时间。例如,如果你设置它为250ms,那么所有运行 250ms 或更久的 SQL 语句将被记录。启用这个参数可以有助于追踪应用中未优化的查询。只有超级用户可以改变这个设置。

对于使用扩展查询协议的客户端,解析、绑定和执行步骤的持续时间将被独立记录。

注意: 当把这个选项和log_statement一起使用时,已经被log_statement记录的语句文本不会在持续时间日志消息中重复。如果你没有使用syslog,我们推荐你使用log_line_prefix记录 PID 或会话 ID,这样你可以使用进程 ID 或会话 ID 把语句消息链接到后来的持续时间消息。

表 19-1解释了PostgreSQL所使用的消息严重级别。如果日志输出被发送到syslog或 Windows 的eventlog,严重级别会按照表中所示进行转换。

表 19-1. 消息严重级别

严重性用法syslogeventlog
DEBUG1..DEBUG5为开发者提供连续的更详细的信息。DEBUGINFORMATION
INFO提供用户隐式要求的信息,例如来自VACUUM VERBOSE的输出。INFOINFORMATION
NOTICE提供可能对用户有用的信息,例如长标识符截断提示。NOTICEINFORMATION
WARNING提供可能出现的问题的警告,例如在一个事务块外COMMITNOTICEWARNING
ERROR报告一个导致当前命令中断的错误。WARNINGERROR
LOG报告管理员可能感兴趣的信息,例如检查点活动。INFOINFORMATION
FATAL报告一个导致当前会话中断的错误。ERRERROR
PANIC报告一个导致所有数据库会话中断的错误。CRITERROR

19.8.3. 记录什么到日志

application_name (string)

application_name可以是任意的小于NAMEDATALEN字字符 (标准编译是64字符)的字符串。它通常由一个连接服务器后的的应用程序设置。 名字会记录在pg_stat_activity和CSV日志条目中。 也可以通过log_line_prefix参数,包含在规律的日志条目中。 只有可打印的ASCII字符可以被用于application_name。 其他字符会被问号(?)替换。 application_name可以是任意小于NAMEDATALEN个字符(标准编译中是 64 个字符)的字符串。这通常由一个应用通过到服务器的连接设置。该名称将被显示在pg_stat_activity视图中并被包括在 CSV 日志项中。它也会被通过log_line_prefix包括在普通日志项中。只有可打印 ASCII 字符能被使用在application_name之中。其他字符将被替换为问号(?)。

debug_print_parse (boolean)
debug_print_rewritten (boolean)
debug_print_plan (boolean)

这些参数将会让多种调试输出被发出。当被设置时,它们为每一个被执行的查询打印结果分析树、查询重写器输出或执行计划。这些消息在LOG消息级别上被发出,因此默认情况下它们将出现在服务器日志中但不会被发送到客户端。你可以通过调整client_min_messages和/或log_min_messages来改变这种情况。这些参数默认是关闭的。

debug_pretty_print (boolean)

当被设置时,debug_pretty_print会缩进由debug_print_parsedebug_print_rewrittendebug_print_plan产生的输出。这将导致比关闭参数时使用的"紧凑"模式可读性更强但是更长的输出。它默认是打开的。

log_checkpoints (boolean)

导致检查点和重启点被记录在服务器日志中。一些统计信息也被包括在日志消息中,包括写入缓冲区的数据和写它们所花的时间。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。默认值是关闭。

log_connections (boolean)

导致每一次尝试对服务器的连接被记录,客户端认证的成功完成也会被记录。 只有超级用户在会话开启时可以改变这个参数,并且在所有会话中不能改变。 缺省是off

注意: 某些客户端程序(例如psql)在要求密码时会尝试连接两次,因此重复的"收到连接"消息并不一定表示一个错误。

log_disconnections (boolean)

记录会话终止原因。日志输出提供信息类似于log_connections, 以及会话持续时间。只有超级用户在会话开启时可以改变这个参数, 并且在所有会话中不能改变。缺省是off

log_duration (boolean)

导致每一个完成的语句的持续时间被记录。默认值是off。只有超级用户可以改变这个设置。

对于使用扩展查询协议的客户端,解析、绑定和执行步骤的持续时间将被独立记录。

注意: 设置这个选项和设置log_min_duration_statement为零之间的区别是,超过log_min_duration_statement强制查询的文本被记录,但这个选项不会。因此,如果log_durationon并且log_min_duration_statement为正值,所有持续时间都将被记录,但是只有超过阈值的语句才会被记录查询文本。这种行为有助于在高负载安装中收集统计信息。

log_error_verbosity (enum)

控制为每一个被记录的消息要写入到服务器日志的细节量。有效值是TERSEDEFAULTVERBOSE,每一个都为显示的消息增加更多域。TERSE排除记录DETAILHINTQUERYCONTEXT错误信息。VERBOSE输出包括SQLSTATE错误码(见附录 A)以及产生错误的源代码文件名、函数名和行号。只有超级用户能够更改这个设置。

log_hostname (boolean)

默认情况下,连接日志消息只显示连接主机的 IP 地址。打开这个参数将导致也记录主机名。注意根据你的主机名解析设置,这可能会导致很微小的性能损失。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

log_line_prefix (string)

这是一个printf风格的字符串,它在每个日志行的开头输出。%字符开始"转义序列",它将被按照下文描述的替换成状态信息。未识别的转义被忽略。其他字符被直接复制到日志行。某些转义只被会话进程识别并且被主服务器进程等后台进程当作空。通过指定一个在%之后和该选项之前的数字可以让状态信息左对齐或右对齐。 负值将导致在右边用空格填充状态信息已达到最小宽度,而正值则在左边填充。填充对于日志文 件的人类可读性大有帮助。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。默认值是一个空字符串。

转义效果只限会话
%a应用名
%u用户名
%d数据库名
%r远程主机名或 IP 地址,以及远程端口
%h远程主机名或 IP 地址
%p进程 ID
%t无毫秒的时间戳
%m带毫秒的时间戳
%n带毫秒的时间戳(作为 Unix 时间戳)
%i命令标签:会话当前命令的类型
%eSQLSTATE 错误代码
%c会话 ID:见下文
%l对每个会话或进程的日志行号,从 1 开始
%s进程开始的时间戳
%v虚拟事务 ID (backendID/localXID)
%x事务 ID (如果未分配则为 0)
%q不产生输出,但是告诉非会话进程在字符串的这一点停止;会话进程忽略
%%纯文字 %

%c转义打印一个准唯一的会话标识符,它由两个 4 字节的十六进制数(不带先导零)组成,以点号分隔。这些数字是进程启动时间和进程 ID,因此%c也可以被用作保存打印这些项的方式的空间。例如,要从pg_stat_activity生成会话标识符,使用这个查询:

SELECT to_hex(trunc(EXTRACT(EPOCH FROM backend_start))::integer) || '.' ||
       to_hex(pid)
FROM pg_stat_activity;

提示: 如果你为log_line_prefix设置了非空值,你通常应该让它的最后一个字符为空格,这样用以提供和日志行的剩余部分的视觉区别。也可以使用标点符号。

提示: Syslog产生自己的时间戳和进程 ID 信息,因此如果你记录到syslog你可能不希望包括哪些转义。

log_lock_waits (boolean)

控制当一个会话为获得一个锁等到超过deadlock_timeout时,是否要产生一个日志消息。这有助于决定是否所等待造成了性能低下。默认值是off

log_statement (enum)

控制哪些 SQL 语句被记录。有效值是 none (off)、ddlmodall(所有语句)。ddl记录所有数据定义语句,例如CREATEALTERDROP语句。mod记录所有ddl语句,外加数据修改语句例如INSERT, UPDATEDELETETRUNCATE, 和COPY FROM。 如果PREPAREEXECUTEEXPLAIN ANALYZE包含合适类型的命令,它们也会被记录。对于使用扩展查询协议的客户端,当收到一个执行消息时会产生日志并且会包括绑定参数的值(任何内嵌的单引号会被双写)。

默认值是none。只有超级用户可以改变这个设置。

注意: 即使设置了log_statement=all,包含 简单语法错误的语句也不会被记录。因为仅在完成基本的语法分析并 确定了语句类型之后才记录日志。在使用扩展查询协议的情况下,在 执行阶段之前(语法分析或规划阶段)同样不会记录。将 log_min_error_statement设为ERROR 或更低才能记录这些语句。 即使使用log_statement = all设置,包含简单语法错误的语句也不会被记录。这是因为只有在完成基本语法解析并确定了语句类型之后才会发出日志消息。在扩展查询协议的情况下,在执行阶段之前(即在解析分析或规划期间)出错的语句也不会被记录。将log_min_error_statement设置为ERROR(或更低)来记录这种语句。

log_replication_commands (boolean)

导致每个复制命令记录在服务器日志中。 参阅第 51.3 节获取更多复制命令的详细信息。 缺省值是off。只有超级用户可以修改这个设置。

log_temp_files (integer)

控制记录临时文件名和尺寸。临时文件可以被创建用来排序、哈希和存储临时查询结果。当每一个临时文件被删除时都会制作一个日志项。一个零值记录所有临时文件信息,而正值只记录尺寸大于或等于指定千字节数的文件。默认设置为 -1,它禁用这种记录。只有超级用户可以更改这个设置。

log_timezone (string)

设置在服务器日志中写入的时间戳的时区。和TimeZone不同,这个值是集簇范围的,因此所有会话将报告一致的时间戳。内建默认值是GMT,但是通常会被在postgresql.conf中覆盖。initdb将安装一个对应于其系统环境的设置。详见第 8.5.3 节。这个参数只能在postgresql.conf文件中或在服务器命令行上设置。

19.8.4. 使用 CSV 格式的日志输出

包括在log_destination中的csvlog,提供了一个 便捷的方式向数据库中导入日志文件。这个选项以CSV格式发出日志行, 带有这些列: 以毫秒为单位的时间戳,用户名,数据库名,进程ID,客户端主机:端口号, 会话ID,每个会话的行号,命令标签,会话开始时间,虚拟事务ID,日常事务ID, 错误严重性,SQLSTATE代码,错误信息,错误信息的详细信息,建议, 导致错误的内部查询(如果存在),其中的错误位置的字符统计, 错误范围,导致错误的用户查询(如果存在,并且启用log_min_error_statement), 其中的错误位置的字符统计,PostgreSQL源代码中报错的位置(如果 log_error_verbosity设置为verbose)和应用程序名。 下面是一个用于存储CSV格式日志暑促的简单表定义: 在log_destination列表中包括csvlog提供了一种便捷方式将日志文件导入到一个数据库表。这个选项发出逗号分隔值(CSV)格式的日志行,包括这些列: 带毫秒的时间戳、 用户名、 数据库名、 进程 ID、 客户端主机:端口号、 会话 ID、 每个会话的行号、 命令标签、 会话开始时间、 虚拟事务 ID、 普通事务 ID、 错误严重性、 SQLSTATE 代码、 错误消息、 错误消息详情、 提示、 导致错误的内部查询(如果有)、 错误位置所在的字符计数、 错误上下文、 导致错误的用户查询(如果有且被log_min_error_statement启用)、 错误位置所在的字符计数、 在 PostgreSQL 源代码中错误的位置(如果log_error_verbosity被设置为verbose)以及应用名。 下面是一个定义用来存储 CSV 格式日志输出的样表:

CREATE TABLE postgres_log
(
  log_time timestamp(3) with time zone,
  user_name text,
  database_name text,
  process_id integer,
  connection_from text,
  session_id text,
  session_line_num bigint,
  command_tag text,
  session_start_time timestamp with time zone,
  virtual_transaction_id text,
  transaction_id bigint,
  error_severity text,
  sql_state_code text,
  message text,
  detail text,
  hint text,
  internal_query text,
  internal_query_pos integer,
  context text,
  query text,
  query_pos integer,
  location text,
  application_name text,
  PRIMARY KEY (session_id, session_line_num)
);

使用COPY FROM命令将一个日志文件导入到这个表中:

COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;

你可以做一些事情来简化导入 CSV 日志文件:

  1. 设置log_filenamelog_rotation_age为你的日志文件提供一种一致的、可预测的命名空间。这让你预测文件名会是怎样以及知道什么时候一个个体日志文件完成并且因此准备好被导入。

  2. log_rotation_size设置为 0 来禁用基于尺寸的日志轮转,因为它使得日志文件名难以预测。

  3. log_truncate_on_rotation设置为on,这样在同一个文件中旧日志数据不会与新数据混杂。

  4. 上述表定义包括一个主键声明。这有助于避免意外地两次导入相同的信息。COPY命令一次提交所有它导入的数据,因此任何错误将导致整个导入失败。如果你导入一个部分完成的日志文件并且稍后当它完全完成后再次导入,主键违背将导致导入失败。请等到日志完成且被关闭之后再导入。这个过程也可以避免意外地导入部分完成的行,这种行也将导致COPY失败。

19.8.5. 进程标题

这些设置控制进程标题如ps是如何被修改的。 参阅第 28.1 节获取详情。

cluster_name (string)

设置出现在集群中的所有进程标题中的集群名称。 名称可以是任何小于NAMEDATALEN字符(标准64字符)的字符串。 只有可输出的ASCII字符可以用在cluster_name值中。 其他字符将用问号替换(?)。 如果此参数设置为空字符串''(即为缺省值),不显示名字。 此参数只能在服务器启动时设置。

update_process_title (boolean)

启用更新进程标题的特性,这个特性在每次服务器接收到一个新SQL命令时都会更新进程的标题。 进程标题通常通过ps命令来查看, 或者在Windows中用进程管理器查看。 只有超级用户可以更改这个设置。