技术细节
- 去 1.2 版
- 用于 go bmizerany/pq 的 postrgres 库
这个问题让我发疯,我希望有人能够提供帮助。
我在 golang 中开发了一个应用程序来从 postgres 数据库中读取数据,并为每条记录发出一个 http 请求,然后更新数据库。
这一切都很简单。但是,我们有 pgbouncer。我们对 pgbouncer 的配置是这样的,它不支持准备好的语句。Go 默默地将所有查询包装在一个准备好的语句中。pgbouncer 的解决方法是设置一个事务。这对于诸如插入/更新/删除之类的事情都很好。
在选择语句的情况下,我将其包装在事务中:
func TransactionQuery(db *sql.DB, baseQuery string) (rows *sql.Rows, code int, err error) {
tx, txErr := db.Begin()
if txErr != nil {
return nil, -1, txErr
}
selectStmt, prepErr := tx.Prepare(baseQuery)
if prepErr != nil {
return nil, -1, fmt.Errorf("Failed to prepare statment: %s Error: %v", baseQuery, prepErr)
}
defer func() {
if stmtErr := selectStmt.Close(); stmtErr != nil {
rows = nil
code = -2
err = fmt.Errorf("Failed to close statement: %v.", stmtErr)
}
}()
rows, err = selectStmt.Query()
if err != nil {
fmt.Errorf("Failed to retrieve data: %v", err)
return nil, -1, err
}
return rows, 0, nil
}
(嗯,这似乎有点让缩进消失了) AsS 你可以看到我开始 bnut 没有关闭交易。这会导致 pg 方面的问题,即每个选择都处于“事务中的空闲”状态。
我已经尝试过 tx.Commit() 和 tx.Rollback() 并且在这两种情况下我都会遇到错误:
"unknown response for simple query '3'"
或者
"unknown response for simple query 'D'"
如何在 Go 中成功关闭交易?我希望更新我们的 pgbouncer.ini 以允许我切换到驱动程序库的 lib/pq,但我不确定这是否会直接帮助解决这个问题。
那么,如何正确关闭 tx 对象,或者有没有办法强制 Go 在后台不使用准备好的语句?
谢谢内森
我试图改变一些事情:
func TransactionQuery(db *sql.DB, baseQuery string) (rows *sql.Rows, code int, err error) {
tx, txErr := db.Begin()
if txErr != nil {
return nil, -1, txErr
}
/*selectStmt, prepErr := tx.Prepare(baseQuery)
if prepErr != nil {
return nil, -1, fmt.Errorf("Failed to prepare statment: %s Error: %v", baseQuery, prepErr)
}
*/
rows, err = tx.Query(baseQuery)
if err != nil {
fmt.Errorf("Failed to retrieve data: %v", err)
return nil, -1, err
}
/* if stmtErr := selectStmt.Close(); stmtErr != nil {
rows = nil
code = -2
err = fmt.Errorf("Failed to close statement: %v.", stmtErr)
}*/
if txCloseErr := tx.Commit(); txErr != nil {
rows = rows
code = -3
err = txCloseErr
}
return rows, 0, nil
}
我在日志中看到的这段代码:
pq: unexpected describe rows response: '3'
但是,我应该指出,这是第二次尝试选择语句时。此应用程序选择一个批次,处理它,然后选择一个后续批次。此错误发生在第二次选择上。第一个选择没有问题。