我正在使用数据库工具(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
语句?
答案 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对象将持续到 除非明确销毁,否则当前会话结束。
因此,必须在每个会话中重新创建这些语句,并且可能我的测试套件在每次运行时都有一个新会话。