如何在PostgreSQL中记录`PREPARE`语句?

时间:2016-12-08 14:29:23

标签: postgresql

我正在使用数据库工具(Elixir的Ecto),它使用prepared statements进行大多数PostgreSQL查询。我想确切地知道它是如何以及何时发生的。

我在postgresql.conf中运行SHOW config_file;找到了正确的Postgres配置文件psql。我把它编辑为包括

log_statement = 'all'

正如Dogbert建议here

根据the PostgreSQL 9.6 docs,此设置应导致PREPARE语句被记录。

重新启动PostgreSQL后,我可以tail -f其日志文件(运行-r可执行文件时由postgres标志指定的文件),我确实看到这样的条目:

LOG:  execute ecto_728: SELECT i0."id", i0."store_id", i0."title", i0."description"
  FROM "items" AS i0 WHERE (i0."description" LIKE $1)
DETAIL:  parameters: $1 = '%foo%'

这对应于查询(尽管通过二进制协议完成,我认为),如

EXECUTE ecto_728('%foo%');

但是,我没有看到创建PREPARE 的原始ecto_728

我尝试删除并重新创建数据库。之后,相同的查询执行为ecto_578,因此似乎原始的预准备语句随数据库一起被删除,并且创建了一个新的语句。

但是当我在PostgreSQL日志中搜索ecto_578时,我只看到它被执行,而不是被创建。

如何在PostgreSQL日志中看到PREPARE语句?

2 个答案:

答案 0 :(得分:2)

正如您所提到的,您的查询是通过扩展查询协议准备的,该协议与<style type="text/css"> .rounded { border-radius:5px; background-color:#87CEEB; border-color:#bce8f1; border-style:solid; border-width:3px; } .articleItem { background-color:#e6f3f7; max-width:700px; border-radius:5px; } .test { font-family: Georgia, serif; font-size: 13px; font-weight: bold; letter-spacing: 1.4px; border-bottom: solid 1px #446e98; text-transform: uppercase; } .content { position:relative; } .imgRight { top:0px; right:0px; max-height:90px; max-width:90px; } .hand:hover { cursor: pointer; } .articleItem:hover { background-color: #d6edf3 !important; } </style> 语句不同。根据{{​​1}}的文档:

  

对于使用扩展查询协议的客户端,在进行日志记录时会发生   收到执行消息

(也就是说,当收到Parse或Bind消息时,记录会发生 not 。)

但是,如果您设置log_min_duration_statement = 0,则:

  

对于使用扩展查询协议的客户端,Parse的持续时间,   绑定和执行步骤是独立记录的

同时启用这两个设置将为每个Execute提供两个日志条目(一个来自PREPARE收到消息,另一个来自log_statement一旦执行完毕)。

答案 1 :(得分:0)

Nick's answer是正确的;我只是通过尝试来回答添加我学到的东西。

首先,我能够在日志中看到三个单独的操作:一个parse用于创建预准备语句,一个bind用于为其提供参数,一个execute为让数据库实际执行并返回结果。这被描述为in the PostgreSQL docs for the "extended query protocol"

LOG:  duration: 0.170 ms  parse ecto_918: SELECT i0."id", i0."store_id",
   i0."title", i0."description"
  FROM "items" AS i0 WHERE (i0."description" LIKE $1)
LOG:  duration: 0.094 ms  bind ecto_918: SELECT i0."id", i0."store_id",
  i0."title", i0."description"
  FROM "items" AS i0 WHERE (i0."description" LIKE $1)
DETAIL:  parameters: $1 = '%priceless%'
LOG:  execute ecto_918: SELECT i0."id", i0."store_id", 
  i0."title", i0."description"
  FROM "items" AS i0 WHERE (i0."description" LIKE $1)
DETAIL:  parameters: $1 = '%priceless%'

此输出是在某些自动化测试运行期间生成的。在后续运行中,我看到了具有不同名称的相同查询 - 例如ecto_1573。这没有丢弃数据库甚至重新启动PostgreSQL进程。 The docs

  

如果成功创建,则命名的prepare-statement对象将持续到   除非明确销毁,否则当前会话结束。

因此,必须在每个会话中重新创建这些语句,并且可能我的测试套件在每次运行时都有一个新会话。