18.8. 错误报告和日志

18.8.1. 在哪里记录日志

log_destination (string)

PostgreSQL支持多种记录服务器日志的方法,包括stderr, csvlog和 syslog。 在Windows里,还支持eventlog。把这个选项设置为一个逗号分隔的日志目标的列表。 缺省是只记录到stderr。这个选项只能在postgresql.conf文件 或者服务器命令行设置。

如果csvlog包含在log_destination中, 日志项是用"逗号分隔"(CSV)格式的输出,这便于加载日志到程序。参见Section 18.8.4获取更多详情。 logging_collector必须能够产生CSV格式的日志输出。

Note: 在大多数Unix系统上,你将需要改变您的系统syslog守护进程的配置, 以便充分利用log_destination的syslog选项。 PostgreSQL可以通过LOCAL7(参见syslog_facility)记录syslog设施LOCAL0, 但缺省大多数平台上syslog配置将忽略所有这样的消息。 你将需要添加类似于下面的信息:

local0.*    /var/log/postgresql

到syslog守护程序的配置文件中,使其工作。

在Windows上,当您使用log_destinationeventlog选项, 你应该注册一个事件源及其操作系统作业库, 使Windows事件查看器可以有规则的显示事件日志信息。 参见Section 17.11获取更多详细信息。

logging_collector (boolean)

这个参数启动日志收集, 这是一个后台进程,抓取发送到stderr的日志消息,并会将他们重定向到日志文件。 这个方法通常比记录到syslog更有用, 因为有些消息类型可能不会出现在syslog输出中 (一个常见的例子是动态连接失败的消息;另外一个是通过脚本比如archive_command 产生的错误消息。) 这个值只能在服务器启动的时候设置。

Note: 不使用日志收集器可以登录到stderr; 无论服务器的stderr被定向到哪,则日志消息就定位到那里。然而, 该方法是只适用于低日志卷,因为它没有提供方便的方式来旋转日志文件。 另外,在某些平台上不使用日志收集器可能会导致丢失或乱码日志输出, 因为多个进程同时写入同一个日志文件可能覆盖彼此的输出。

Note: 日志收集器设计永远不会丢失消息。 这意味着在非常高的负载情况下, 当收集器已经落后而试图发送额外的日志消息的时候,封锁服务器进程。 与此相反,syslog更喜欢忽略消息, 如果它无法写入,这意味着它可能无法记录这些消息,这种情况下, 但它不会阻止该系统的其余部分。

log_directory (string)

在打开了logging_collector的时候,这个选项判断日志文件在哪个目录里创建。 它可以声明成绝对路径,或者是与集群的数据目录相对的路径。 这个选项只能在postgresql.conf文件里或者服务器命令行设置。

log_filename (string)

在打开了logging_collector的时候,这个选项设置所创建的日志文件的文件名。 这个数值将被当作strftime模式看待。因此可以用%逃逸声明随时间而变的文件名。 (注意,如果有任何时区相关%逃逸,由log_timezone声明的时区进行计算。) 支持的%逃逸类似于Open Group上的strftime规范列表中的。 注意,不直接使用这个系统的strftime,所以特定平台的(非标准)扩展不起作用。

如果您没有逃逸指定文件名,你应该计划使用日志旋转程序以避免最终填充 整个磁盘。在8.4之前的版本中,如果没有%的转义符出现, PostgreSQL将追加新日志文件创建时间的时间戳, 但是不再是这种情况了。

如果启用log_destination中的CSV格式输出, .csv将追加时间戳日志文件名来创建CSV格式输出的文件名。 (如果log_filename.log为结束,后缀代替)。 在上面的例子情况下,CSV文件名是server_log.1093827753.csv

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

log_file_mode (integer)

在Unix系统上,当logging_collector已启用时(在Microsoft Windows上将忽略此参数), 此参数用于设置日志文件的权限。 该参数值预期为通过chmodumask 系统调用接受的格式指定的数字模式。 (为了使用习惯八进制格式的数字必须以0(zero)开始)。

默认的权限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 覆盖而不是附加到任何同名的现有日志文件上。 不过,覆盖只是发生在基于时间滚动而创建的新文件上,而不是在服务器启动的时候或者以尺寸为基础的滚动上。 如果为 off ,将始终向已存在的文件结尾追加。比如, 使用这个选项和类似postgresql-%H.log这样的log_filename设置将导致生成 24个按小时生成的日志文件然后在这些文件上循环。 这个选项只能在postgresql.conf文件里或者在服务器启动的时候设置。

例子:保留 7 天的日志,每天一个日志文件,叫做server_log.Mon, server_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。 在log_filename里包含%M 允许任何尺寸驱动的旋转选取一个和开始的文件名同小时数但是名字不同的文件。

syslog_facility (enum)

如果向syslog进行记录,那么这个选项判断要使用的syslog"设施"。 你可以从LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7中选择。缺省是LOCAL0。 又见你的系统的syslog守护进程文档。 这个选项只能在postgresql.conf文件里或者服务器启动的时候设置。

syslog_ident (string)

如果向syslog进行记录,这个选项决定用于在syslog日志中标识PostgreSQL的程序名。 缺省是postgres。这个选项只能在postgresql.conf文件里或者服务器启动的时候设置。

event_source (string)

当启用记录event log时,此参数 确定用于识别PostgreSQL消息日志的程序名称。 缺省是PostgreSQL。 该参数只能在postgresql.conf文件或者服务器命令行上设置。

18.8.2. 什么时候记录日志

client_min_messages (enum)

这个选项控制哪些信息发送到客户端。 有效的数值是DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, LOG, NOTICE, WARNING, ERROR, FATAL, 和PANIC。 每个级别包含所有它后面的级别,级别越靠后,发送的信息越少。缺省是NOTICE。 需要注意的是这里的LOGlog_min_messages里的级别不同。

log_min_messages (enum)

控制写到服务器日志里的信息的详细程度。 有效值是DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATALPANIC。 每个级别都包含它后面的级别。越靠后的数值发往服务器日志的信息越少。缺省是WARNING。 需要注意的是这里的LOGclient_min_messages里的级别不同。只有超级用户可以修改这个设置。

log_min_error_statement (enum)

控制在服务器日志里输出哪一条导致错误条件的SQL语句。 所有导致一个特定级别(或者更高级别)错误的 SQL 语句都要被记录。 有效的值有DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATALPANIC。 缺省是ERROR, 表示所有导致错误、日志信息,致命错误、恐慌的SQL语句都将被记录。 设置为PANIC表示把这个特性关闭。只有超级用户可以改变这个设置。

log_min_duration_statement (integer)

如果某个语句的持续时间大于或者等于这个毫秒数,那么在日志行上记录该语句及其持续时间。 设置为零将打印所有查询和他们的持续时间。设置为-1(缺省值)关闭这个功能。比如, 如果你把它设置为250ms,那么所有运行时间等于或者超过 250ms 的 SQL 语句都会被记录。 打开这个选项可以很方便地跟踪需要优化的查询。只有超级用户可以改变这个设置。

对于使用扩展查询协议的客户端,语法分析、邦定、执行每一步所花时间都分别记录。

Note: 当此选项与log_statement同时使用时, 已经被log_statement记录的语句文本不会被重复记录。 如果没有使用syslog的话,推荐使用log_line_prefix记录 PID 或会话ID, 这样就可以使用它们将语句消息连接耗时消息。

Table 18-1解释了PostgreSQL使用的 信息严重程度。如果日志输出发送到syslog或者Windows的 eventlog,则严重程度如下表所示。

Table 18-1. 信息严重级别

严重级别 用法 syslog eventlog
DEBUG1..DEBUG5 提供开发人员使用的连续更多详细信息 DEBUG INFORMATION
INFO 提供用户隐含要求的信息,比如在VACUUM VERBOSE过程输出的信息。 INFO INFORMATION
NOTICE 提供可能对用户有帮助的信息,比如,长标识符的截断 NOTICE INFORMATION
WARNING 提供可能问题的警告,比如在事务块范围之外的COMMIT NOTICE WARNING
ERROR 报告导致当前命令退出的错误。 WARNING ERROR
LOG 报告一些管理员感兴趣的信息,比如,检查点活跃性。 INFO INFORMATION
FATAL 报告导致当前会话终止的错误。 ERR ERROR
PANIC 报告导致所有数据库会话退出的错误。 CRIT ERROR

18.8.3. 记录什么

application_name (string)

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_parse, debug_print_rewritten或者debug_print_plan产生的消息, 这样更加可读,但是,当关闭它时,比"紧凑型"格式更长的输出,缺省是打开的。

log_checkpoints (boolean)

导致检查点和重启点被记录在服务器日志中。 一些统计都包含在日志信息中,包括缓冲区写入数量和编写它们的花费的时间。 这些参数只能在postgresql.conf文件或者服务器命令行上设置,缺省是off。

log_connections (boolean)

导致记录到服务器的每个尝试连接,以及成功完成客户端认证。 该参数在会话开始之后不能改变,缺省是off。

Note: 某些客户端程序,如psql当确定是否需要密码的时候, 企图连接两次。所以复制"连接收到"的消息不一定表示有问题。

log_disconnections (boolean)

这个选项类似log_connections,但是在会话结束的时候在服务器日志里输出一行。 并且包含会话持续时间。 缺省是关闭的。这个参数在会话开始之后不能被改变。

log_duration (boolean)

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

对于使用扩展查询协议的客户端,语法分析、邦定、执行每一步所花时间都分别记录。

Note: 设置为0时该选项与log_min_duration_statement 的不同之处在于log_min_duration_statement 强制记录查询文本。但是这个选项不可以。因此,如果log_durationon并且log_min_duration_statement 大于零将记录所有持续时间,但是仅记录那些超过阈值的语句。 这可以用于在高负载情况下搜集统计信息。

log_error_verbosity (enum)

控制记录的每条信息写到服务器日志里的详细程度。 有效的值是TERSE,DEFAULTVERBOSE, 逐个向显示的信息里增加更多的字段。TERSE包含 DETAIL的记录, HINT,QUERYCONTEXT错误信息。 VERBOSE输出包含SQLSTATE错误代码 (参见Appendix A)以及源代码文件名称,函数名称,以及产生错误的行数。 只有超级用户可以改变这个设置。

log_hostname (boolean)

缺省时,连接日志只记录所连接主机的IP地址。打开这个选项导致同时记录主机名。 请注意,这样有可能带来一些不可忽略的性能损失(取决于你的名字解析的设置)。 这个选项只能在postgresql.conf文件里或者服务器命令行设置。

log_line_prefix (string)

这是一个printf风格的字符串,在日志的每行开头输出。 %字符开始"转义序列"被如下所述状态信息替换。 无法识别的转义被忽略。其它字符都直接拷贝到日志行中。 有些逃逸只被会话进程识别,被后端进程忽略,比如主服务器进程。 这个选项只能在postgresql.conf文件里或者服务器命令行设置。 缺省是空字符串。

逃逸 效果 仅用于会话
%a Application name yes
%u User name yes
%d Database name yes
%r Remote host name or IP address, and remote port yes
%h Remote host name or IP address yes
%p Process ID no
%t Time stamp without milliseconds no
%m Time stamp with milliseconds no
%i Command tag: type of session's current command yes
%e SQLSTATE error code no
%c Session ID: see below no
%l Number of the log line for each session or process, starting at 1 no
%s Process start time stamp no
%v Virtual transaction ID (backendID/localXID) no
%x Transaction ID (0 if none is assigned) no
%q Produces no output, but tells non-session processes to stop at this point in the string; ignored by session processes no
%% Literal % no

%c逃逸打印唯一会话标识符, 由两个点号分隔的4字节的十六进制数字(没有前导零)组成。 数字是该过程的开始时间和进程ID, 所以%c也可以用做一种打印这些项目的节约空间的方法。 例如,为了从pg_stat_activity中生成会话标识符,使用这个查询:

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

Tip: 如果你设置log_line_prefix的非空值,你应该经常使其最后一个字符是一个空格, 提供来自日志行的其余部分的视觉分离。一个标点符号也可以使用。

Tip: Syslog产生自身时间戳和进程ID信息,如果你记录到syslog, 所以你可能不想包括那些逃脱。

log_lock_waits (boolean)

当会话等待比deadlock_timeout获得锁更长的时间时,控制是否产生一个日志消息。 决定如果锁等待造成很差的性能,这是很有用处的。默认是off

log_statement (enum)

控制记录哪些SQL语句。有效的值是none (off), ddl, modall (所有语句)。ddl记录所有数据定义命令,比如CREATE, ALTERDROP语句。 mod记录所有ddl语句, 加上数据修改语句INSERT,UPDATE, DELETE, TRUNCATE, 和COPY FROM。如果所包含的命令类型吻合,那么PREPARE, EXECUTEEXPLAIN ANALYZE语句也同样被记录。 对于使用扩展查询协议的客户端,记录发生在接受到扩展信息并包含邦定参数(内置单引号要双写)的时候。

缺省是none。只有超级用户可以改变这个设置。

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

log_temp_files (integer)

控件的临时文件名称和大小。临时文件可以创建的分类,哈希,和临时的查询结果。 当它被删除时,一个日志项有利于每个临时文件。 零值记录所有临时文件的信息, 同时正值记录文件大小大于或等于千字节指定数量。 默认设置是-1,禁用这样的日志。只有超级用户可以更改此设置。

log_timezone (string)

设置用于写入服务器日志的时间戳的时区。不像TimeZone,这个值是簇范围, 因此,所有会话将持续报告时间戳。默认值GMT,但这通常被 postgresql.conf覆盖;initdb 将安装与其系统环境一致的设置。参见Section 8.5.3获取更多信息。 这个参数只能在postgresql.conf文件或者服务器命令行上进行。

18.8.4. 使用CSV-格式日志输出

log_destination列表中包含csvlog 提供了一种便捷的方式导入日志文件到一个数据库表。 此选项在逗号分隔值(CSV)中发出日志行,这些列为: time stamp with milliseconds, user name, database name, process ID, client host:port number, session ID, per-session line number, command tag, session start time, virtual transaction ID, regular transaction ID, error severity, SQLSTATE code, error message, error message detail, hint, 导致错误的内部查询(如果有),字符计算错误位置, 包含错误文本,导致错误的用户查询(如果有并且通过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_rotationon,以致于 旧的日志数据不与同一文件的新数据混合。

  4. 上面表定义包括主密钥规范。这是为了防止意外导入相同的有用信息两次。 COPY命令要求所有的数据一次导入,所以任何错误都将导致整个导入过程失败。 如果你导入部分日志文件,当它完成时,然后再导入该文件,主键冲突会导致导入过程失败。 等待直到日志是完整的,并且导入之前关闭。 该程序也将防止意外导入尚未完全写入的局部行, 这也将导致COPY失败。