PQ驱动程序:预处理语句不存在

9

我正在尝试使用Go语言的pq驱动程序连接到PostgreSQL数据库。当我在本地数据库副本上使用连接字符串时,例如:

DB, err = sql.Open("postgres", "user=user password=pwd dbname=mydb sslmode=disable")

所有功能都运作良好。

但是,当我切换到一个连接经过 pgbouncer 的生产服务器时:

DB, err = sql.Open("postgres", "user=user password=pwd host=/var/run/pgbouncer port=port dbname=mydb sslmode=disable")

我对所有查询都不管多简单,总是得到同样的错误:

Database error: pq: S:"ERROR" M:"prepared statement \"1\" does not exist" C:"26000" F:"prepare.c" L:"519" R:"FetchPreparedStatement"

无论我尝试传递的查询是什么,它总是“prepared statement \”1\“”。

在这两种情况下,查询都是简单地运行如下:

res_rows, err := DB.Query(query)
if err != nil {
    log.Printf("Database error: %s\n", err)
}
for res_rows.Next() {
    ...
}

通过谷歌搜索得知可以关闭预处理语句,但我不知道如何在Go中实现这一点,也不确定是否支持。非常感谢任何帮助(甚至是建议使用完全不同的东西)。


你要求我们猜测你运行了哪些查询导致了错误。你执行了哪些查询和相关方法,例如Prepare方法,来引起这个错误? - peterSO
抱歉,我更新了帖子。我根本没有使用Prepare,只是在sql.Open之后直接使用了普通的DB.Query。 - snikolenko
4个回答

5
如果您正在使用 PgBouncer,需要将binary_parameters=yes作为查询参数设置到您的数据库dsn连接中。
请尝试以下操作:
DB, err = sql.Open("postgres", "user=user password=pwd dbname=mydb sslmode=disable, binary_parameters=yes")

4

Package driver

type Queryer

type Queryer interface {
    Query(query string, args []Value) (Rows, error)
}

Queryer is an optional interface that may be implemented by a Conn.

If a Conn does not implement Queryer, the sql package's DB.Query will first prepare a query, execute the statement, and then close the statement.

我没有看到 lib/pq PostgreSQL 驱动实现了 Queryer 接口。因此,DB.Query 查询在执行之前被准备好。

PgBouncer 不支持所有连接池方法的 PREPARE 特性:连接池模式功能矩阵


谢谢您的解释!那么基本上这意味着我不能在这种设置中使用Go语言? - snikolenko

4
Postgres驱动现在有解决这个问题的方案:https://github.com/lib/pq/issues/389。虽然没有在文档中提及,但它能如预期地工作,包括启用了PgBouncer和事务池。

0
自 PgBouncer 1.21.0 版本开始,它现在支持协议级别的命名预处理语句,这几乎可以解决此错误。您可以通过在 PgBouncer 的配置文件中将 max_prepared_statements 设置为非零值来启用此支持。有关详细信息,请查阅文档:https://www.pgbouncer.org/config.html#max_prepared_statements

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