技术细节
- go版本1.2
- 使用go语言库bmizerany/pq访问postgres数据库
这个问题让我非常疑惑,我希望有人能够帮助我。
我开发了一个golang应用程序,可以从postgres数据库读取数据,并为每条记录进行http请求,然后更新数据库。
这很简单。然而,我们安装了pgbouncer。我们对pgbouncer的配置是不支持预处理语句。Go会自动将所有查询语句包装在预处理语句中。解决pgbouncer的方法是建立一个事务。这对于类似插入/更新/删除的操作来说都很好。
对于我所使用的select语句,我将其包装在事务中:
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
}
(嗯,这似乎有点打乱缩进)如您所见,我开始了事务但未关闭它。这会导致在pg方面的问题,其中每个select都处于“空闲事务”状态。
我尝试了tx.Commit()和tx.Rollback(),但两种情况都出现了错误:
"unknown response for simple query '3'"
或者
"unknown response for simple query 'D'"
我希望能够成功关闭Go中的交易。我希望更新我们的pgbouncer.ini文件以允许我切换到lib/pq驱动程序库,但我不确定这是否会直接解决此问题。
那么,我应该如何正确关闭tx对象,还是有办法强制Go在幕后不使用预处理语句?
谢谢 Nathan
我已经尝试过做出一些改变:
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'
但是,我应该指出的是,在尝试第二次选择语句时出现这种情况。此应用程序选择一批数据进行处理,然后选择随后的一批数据。这个错误发生在第二个选择过程中。第一个选择没有任何问题。