技術詳細
- バージョン1.2に行く
- go bmizerany/pq の postrgre ライブラリ
この問題は私を怒らせており、誰かが助けてくれることを願っています.
postgresデータベースからデータを読み取り、レコードごとにhttpリクエストを作成してデータベースを更新するアプリケーションをgolangで開発しました。
これはすべて簡単です。ただし、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
}
(うーん、インデントが少しずれているようです) おわかりのように、トランザクションを閉じずに 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'
ただし、これは select ステートメントを 2 回目に試行する場合であることを指摘しておく必要があります。このアプリケーションは、バッチを選択して処理し、後続のバッチを選択します。このエラーは、2 番目の選択で発生します。最初の選択に問題はありません。