如何记录PostgreSQL查询?

480

如何启用记录PostgreSQL 8.3执行的所有SQL语句的日志记录?

编辑(更多信息) 我改变了这些行:

log_directory = 'pg_log'                    
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_statement = 'all'

我重启了PostgreSQL服务...但是没有生成日志... 我使用的是Windows Server 2003操作系统。

有什么想法吗?


28
重要提示:logging_collector = on。 (Explanation: This is a configuration setting for logging in a software system. The original text is already concise and clear, so I translated it directly without changing its meaning.) - bonyiii
另外,请注意,在某些GNU/Linux发行版(例如Debian Jessie)上,“systemctl restart postgresql”可能实际上不会重新启动您配置的PostgreSQL服务(我还不明白为什么),因此配置文件中的更改将不会应用。更安全的方法是使用“pg_ctl”(或在Debian上使用“pg_ctlcluster”)。 - Skippy le Grand Gourou
6
我刚在Ubuntu 16.04 LTS上测试了这个,使用PostgreSQL 9.5,执行systemctl reload postgresqlsystemctl restart postgresqlservice postgresql reloadservice postgresql restart都会使配置更改生效。 - Ben Johnson
在我的情况下(Win 10 桌面,pg12),我必须使用 ALTER DATABASE 明确启用实际数据库的日志记录(如此答案中所述)。 - Janaka Bandara
14个回答

548

在你的data/postgresql.conf文件中,将log_statement设置更改为'all'


编辑

看着你提供的新信息,我认为可能还有其他一些需要验证的设置:

  • 确保你已经打开了log_destination变量
  • 确保你打开了logging_collector
  • 同时确保log_directory目录已存在于data目录内,并且postgres用户可以对其进行写入。

4
那么,只是好奇,这是否意味着除非我重新启动服务器,否则无法启用PostgreSQL日志记录?在MySQL中,只需执行“SET GLOBAL general_log = 'ON';”即可。 - Antony
9
我个人不知道是否有一种类似于MySQL的SQL语句的方式来实现它,但是您可以向正在运行的PostgreSQL服务器发送pg_ctl reload命令以重新加载配置。 - Jarret Hardie
10
截至9.2版本,PostgreSQL还没有通过SQL语句更改参数的方法。大多数日志记录参数可以通过执行"pg_ctl reload"而不必完全重新启动服务器来更改。然而,更改"logging_collector"参数需要重新启动服务器才能生效。 - Greg Smith
8
使用Postgres 9.4和新的ALTER SYSTEM命令,超级用户可以通过SQL设置GUC参数。 - Erwin Brandstetter
11
答案中提到的data目录并不是它的字面名称;它指的是在PostgreSQL配置文件中分配给data_directory变量的路径。在Debian和Ubuntu GNU/Linux上,该文件通常位于/etc/postgresql/$v/main/postgresql.conf,其中$v是服务器版本。此外,在这些系统上,当log_destination = 'stderr'时,输出将写入/var/log/postgresql/postgresql-$v-main.log,其中$v是服务器版本(而不是data_directory内部的某个位置)。 - Ben Johnson
显示剩余6条评论

149

编辑您的/etc/postgresql/9.3/main/postgresql.conf文件,并按以下方式更改行。

注意:如果找不到postgresql.conf文件,请在终端中键入$locate postgresql.conf

  1. #log_directory = 'pg_log' 更改为 log_directory = 'pg_log'

  2. #log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' 更改为 log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'

  3. #log_statement = 'none' 更改为 log_statement = 'all'

  4. #logging_collector = off 更改为 logging_collector = on

  5. 可选SELECT set_config('log_statement', 'all', true);

  6. sudo /etc/init.d/postgresql restart 或者 sudo service postgresql restart

  7. 在postgresql中执行查询select 2+2

  8. /var/lib/pgsql/9.2/data/pg_log/中查找当前日志

随着时间的推移,日志文件往往会增长很多,并可能导致机器崩溃。为了安全起见,请编写一个Bash脚本来删除日志并重新启动postgresql服务器。

感谢@paul,@Jarret Hardie ,@Zoltán,@Rix Beck,@Latif Premani


3
在Debian Stretch系统中,我还需要在配置文件中取消注释# log_destination = 'stderr'才能使其正常工作。 - phihag
我仔细按照你的步骤操作了,但它并没有起作用。需要重新启动吗? - Yohanim
3
如果您不想编写一个bash脚本,只是想使日志每月覆盖一次,请使用以下代码:log_filename = 'postgresql-%d.log'。不用担心,它不会在每次重启后覆盖文件,而是每天都会追加内容,并且每个月会覆盖旧的记录。当然,不同的月份有28、29、30、31天等等,但您应该能明白意思。 - sojim2
我发现自从Postgres 9.0以来,你可以运行select pg_reload_config(); 而不必在第6步重启服务。 - jamesthollowell
值得注意的是,更改 logging_collector = on 需要重新启动服务器 - 即运行 SELECT pg_reload_conf(); 可以与其他 postgresql.conf 参数一起工作,但不能与该参数一起工作 - 您可以在重新加载后运行 SELECT name, pending_restart FROM pg_settings WHERE name = 'logging_collector'; 来检查这一点。这真是遗憾 - 我认为这最多是个小问题,最坏的情况下是个错误。 - undefined

92

供参考:其他解决方案仅记录来自默认数据库(通常为postgres)的语句。要记录其他数据库,请使用他们的解决方案,然后:

最初的回答:

ALTER DATABASE your_database_name
SET log_statement = 'all';

参考:https://serverfault.com/a/376888 / log_statement

"Original Answer"的意思是"最初的回答"。

如果您想了解有关IT技术的更多信息,请参阅上面提供的链接。


2
这应该是被接受的答案 - 唯一一个具有实际价值的答案! - Janaka Bandara
2
引用的语句在Postgres 9.4或更高版本中有效,但前面的段落是错误的。在“postgresql.conf”中设置log_statement = all 对于相应的数据库集群 - 如所接受的答案建议的那样 - 影响该集群中所有数据库 - 可以被每个数据库的设置覆盖。 - Erwin Brandstetter
3
重新连接 psql 以生效。 - Daniil Iaitskov

53
SELECT set_config('log_statement', 'all', true);

在连接后,具有相应用户权限的用户可以使用上述查询。这将影响日志记录,直到会话结束。


9
通常更清晰的方法是使用SET log_statement = 'all'或(对于事务级别)SET LOCAL log_statement ='all'。您可能还会对client_min_messageslog_min_messages设置感兴趣。 - Craig Ringer
1
这很好,因为我只想记录我的连接消息。不幸的是,由于我的用户不是超级用户,所以我收到了“无权设置参数“log_statement”的权限被拒绝”的错误提示。 - guettli
3
您可以向数据库管理员请求授予执行该函数的权限。GRANT { EXECUTE | ALL [ PRIVILEGES ] } ON { FUNCTION function_name ( [ [ argmode ] [ arg_name ] arg_type [, ...] ] ) [, ...] | ALL FUNCTIONS IN SCHEMA schema_name [, ...] } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] - Rix Beck

42

您还需要在PostgreSQL中添加这些行并重新启动服务器:

log_directory = 'pg_log'                    
log_filename = 'postgresql-dateformat.log'
log_statement = 'all'
logging_collector = on

2
logging_collector=on 是必要的。 - wjin
运行得非常好。我曾经被配置文件中的注释所困惑,它说“必须打开以进行csv日志记录”,我认为这个选项是用来记录查询输出而不仅仅是语句,但事实并非如此。 - Jacopofar
在您的 data/postgresql.conf 文件中,将 log_statement 设置更改为“all”。 - FlyingV

28

21

以上回答都很好。我使用以下配置

log_line_prefix = '%t %c %u ' # time sessionid user
log_statement = 'all'

13

根据这个网页上的说明,以下是关于运行PostgreSQL 9.2的CentOS 6.4 (Red Hat 4.4.7-3)更多详细信息:

  1. /var/lib/pgsql/9.2/data/postgresql.conf中设置(取消注释)log_statement = 'all'log_min_error_statement = error
  2. 重新加载PostgreSQL配置。 对于我来说,这是通过运行/usr/pgsql-9.2/bin/pg_ctl reload -D /var/lib/pgsql/9.2/data/完成的。
  3. /var/lib/pgsql/9.2/data/pg_log/中查找今天的日志

4
不需要重新启动 - 运行 pg_ctl reload 命令就足够了,而且不会中断连接。我不确定这个答案是否有助于已经存在的答案。 - Craig Ringer
1
@CraigRinger 感谢您的评论,这是非常重要的事实。一旦我尝试了您的建议,我将更新答案。我主要为自己写这个答案,因为当时我对UNIX几乎没有经验,我想把所有必要的信息放在一个地方(例如postgresql.conf和日志文件的位置)。 - Zoltán

5

postgresql有一个相关扩展名为"pg_stat_statements",可用于此目的。 https://www.postgresql.org/docs/9.4/pgstatstatements.html

基本上你需要稍微修改一下postgresql.conf文件:

shared_preload_libraries= 'pg_stat_statements'
pg_stat_statements.track = 'all'

然后您需要登录到数据库并运行此命令:

create extension pg_stat_statements;

它将创建名为"pg_stat_statements"的新视图。在这个视图中,你可以看到所有已执行的查询。

3
动态地启用/禁用日志记录有两种方法:
  1. 更改数据库中的全局变量并重新加载配置 a) 设置log_statement = 'all'; 或设置log_min_duration_statement = 0; b) 选择pg_reload_conf();
  2. 从Linux命令行编辑postgres配置文件,更改与日志记录相关的参数 log_min_duration_statement = 0 log_statement = 'all' 重新加载配置文件 su - postgres /usr/bin/pg_ctl reload
在这两种情况下,我们不应该重启Postgres。我们可以通过重新加载配置来动态地启用/禁用日志记录。
希望这对您有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接