问题
当某些应用程序使用扩展查询协议/准备好的语句来查询 Postgres(出于性能原因,您通常应该这样做)并由于某种原因获得查询错误或只是超过“慢查询日志”阈值(log_min_duration_statement配置参数)时,您将无法在查询日志中获得完整的可执行语句!而是 2 个部分 - 一个带有美元类型占位符的查询,然后是实际参数值列表 - 如果您想要实际重新运行查询(主要使用 EXPLAIN ANALYZE)并查看为什么这个特定的参数值组合很慢,则需要“填写”它们。
解决方案
以前,如果需要重新运行一些参数化的准备好的语句,我会执行以下操作之一:
手动替换/填充
如果是单个或几个查询,且占位符/参数数量较少,请检查日志文件并手动填写空白。没什么大不了的,好吧,我想偶尔做点工作。
使用我的临时脚本
当参数数量太大(10+)或需要处理许多查询/执行时,我查看了自制的参数匹配/填充 Python 脚本的位置,并希望它能够适用于特定的日志配置……因为它是一个非常简单的正则表达式匹配行迭代器,仅支持log_line_prefix我主要处理的几种常见格式。
但是现在 - pgbadger 来救援了!
每个接触过 Postgres 的人都喜欢pgbadger,对吧?我也是。但有趣的是 - 这个工具的唯一缺点是它有大量的命令行参数…我数了一下,大约有一百个,不是开玩笑!
所以,最后,在最近的一个幸运的日子,我因为其他原因再次浏览了所有这些标志…并发现了:
--dump-all-queries : dump all queries found in the log file replacing
bind parameters included in the queries at their
respective placeholders positions.
瞧!
演示用法
实际情况是这样的:
$ pgbench -i
$ PGOPTIONS='-c log_min_duration_statement=0' pgbench -M prepared -n -S -t 2
$ cat postgresql.log
...
2023-06-07 18:07:45.908 EEST [250162] LOG: duration: 0.203 ms parse P_0: SELECT abalance FROM pgbench_accounts WHERE aid = $1;
2023-06-07 18:07:45.908 EEST [250162] LOG: duration: 0.220 ms bind P_0: SELECT abalance FROM pgbench_accounts WHERE aid = $1;
2023-06-07 18:07:45.908 EEST [250162] DETAIL: parameters: $1 = '93026'
2023-06-07 18:07:45.908 EEST [250162] LOG: duration: 0.026 ms execute P_0: SELECT abalance FROM pgbench_accounts WHERE aid = $1;
2023-06-07 18:07:45.908 EEST [250162] DETAIL: parameters: $1 = '93026'
2023-06-07 18:07:45.908 EEST [250162] LOG: duration: 0.020 ms bind P_0: SELECT abalance FROM pgbench_accounts WHERE aid = $1;
2023-06-07 18:07:45.908 EEST [250162] DETAIL: parameters: $1 = '26950'
2023-06-07 18:07:45.908 EEST [250162] LOG: duration: 0.025 ms execute P_0: SELECT abalance FROM pgbench_accounts WHERE aid = $1;
2023-06-07 18:07:45.908 EEST [250162] DETAIL: parameters: $1 = '26950'
$ pgbadger --dump-all-queries postgresql.log
[========================>] Parsed 2165 bytes of 2165 (100.00%), queries: 4, events: 1
$ cat out.txt
...
SELECT abalance FROM pgbench_accounts WHERE aid = '93026';
SELECT abalance FROM pgbench_accounts WHERE aid = '26950';
PS请注意,如果 pgbadger 调用失败或没有得到正确的结果,则可能是日志格式自动检测出现了问题(尽管大部分情况下都能正常工作!)并且需要通过参数提供帮助–prefix。
PS 2还要注意,实际的准备好的语句参数值并不总是保证存在,因为它们可以通过相对未知的log_parameter_max_length和log_parameter_max_length_on_error参数在敏感环境中被禁用 - 在这种情况下,当然即使是拥有 100 个参数的万能的 pgbadger 也无法帮助你:傻笑:
#PG考试#postgresql培训#postgresql考试#postgresql认证