Postgresql 中文操作指南

25.3. Log File Maintenance #

最好将数据库服务器的日志输出保存在某处,而不是通过 /dev/null 直接丢弃。在诊断问题时,日志输出是无价的。

Note

服务器日志可能包含敏感信息,无论它如何存储或存储在哪里,或者路由到的目的地是什么,都需要对其进行保护。例如,某些 DDL 语句可能包含明文密码或其他身份验证详细信息。ERROR 级别的日志语句可能显示应用程序的 SQL 源代码,还可能包含一些数据行的部分内容。记录数据、事件和相关信息是此功能的预期功能,因此这不属于泄漏或错误。请确保只有经过适当授权的人员才能看到服务器日志。

日志输出往往很冗长(尤其是在更高的调试级别),因此您不会想要无限期地保存它。您需要 rotate 日志文件,以便在一段时间后启动新的日志文件并删除旧日志文件。

如果您只是将 postgres 的 stderr 指向文件,您将拥有日志输出,但截断日志文件的唯一方法是停止并重新启动服务器。如果您在开发环境中使用 PostgreSQL,这可能可以接受,但很少有生产服务器会发现这种行为可以接受。

一个更好的方法是将服务器的 stderr 输出发送到某种日志轮换程序。服务器内置日志轮换功能,您可以通过在 postgresql.conf 中将配置参数 logging_collector 设置为 true 来使用该功能。此程序的控制参数如 Section 20.8.1 中所述。您还可以使用这种方法以机器可读 CSV(逗号分隔值)格式捕获日志数据。

或者,如果您已经与其他服务器软件一起使用外部日志轮换程序,您可能更喜欢使用它。例如,Apache 发行版中包含的 rotatelogs 工具可以与 PostgreSQL 一起使用。执行此操作的一种方法是将服务器的 stderr 输出管道输入到所需的程序。如果您使用 pg_ctl 启动服务器,则 stderr 已重定向到 stdout,因此您只需要一个管道命令,例如:

pg_ctl start | rotatelogs /var/log/pgsql_log 86400

您可以通过将 logrotate 设置为收集 PostgreSQL 内置日志收集器产生的日志文件来组合这些方法。在此情况下,日志收集器定义日志文件的文件名和位置,而 logrotate 定期归档这些文件。在启动日志轮换时,logrotate 必须确保应用程序将进一步的输出发送到新文件。这通常是通过一个 postrotate_脚本来完成的,该脚本向应用程序发送一个 _SIGHUP 信号,然后应用程序重新打开日志文件。在 PostgreSQL 中,您可以运行带有 logrotate 选项的 pg_ctl。当服务器收到此命令时,会根据日志配置(请参见 Section 20.8.1),切换到新日志文件或重新打开现有日志文件。

Note

使用静态日志文件名时,如果达到最大打开文件限制或出现文件表溢出,服务器可能无法重新打开日志文件。在这种情况下,日志消息会发送到旧日志文件,直到成功进行日志轮换。如果配置日志轮换来压缩日志文件并将其删除,则服务器可能会丢失此时间段内记录的消息。要避免此问题,您可以将日志收集器配置为动态分配日志文件名,并使用 prerotate 脚本忽略打开的日志文件。

管理日志输出的另一个生产级方法是将其发送到 syslog 并让 syslog 处理文件轮换。要执行此操作,请在 postgresql.conf 中将配置参数 log_destination 设置为 syslog(仅记录到 syslog)。然后您可以随时向 syslog 守护程序发送 SIGHUP 信号以强制它开始写入新的日志文件。如果您想要自动执行日志轮换,可以将 logrotate 程序配置为使用 syslog 的日志文件。

然而,在许多系统上,syslog 的可靠性不是很好,尤其是在日志消息很大的情况下;它可能在你最需要它们的时候截断或丢弃消息。此外,在 Linux 上,syslog 将刷新每个消息到磁盘,从而产生较差的性能。(您可以在 syslog 配置文件的文件名开头使用“-”来禁用同步。)

请注意,上面描述的所有解决方案都会在可配置的时间间隔内启动新日志文件,但它们不会处理不再有用的旧日志文件的删除。您可能需要设置一个批处理作业来定期删除旧日志文件。另一种可能性是配置轮换程序,以便旧日志文件被循环覆盖。

pgBadger 是一个执行复杂日志文件分析的外部项目。 check_postgres 提供 Nagios 警报,当日志文件中出现重要消息时,以及检测许多其他异常情况时。