ゴラン - PGBouncerとトランザクションの使用法
-
21-12-2019 - |
質問
Tech Detail
- Goバージョン1.2
- GO BMIZERANY / PQ 用POSTRGRESライブラリ
この問題は私を怒らせています、そして誰かが助けることができることを願っています。
Postgresデータベースからデータを読み取るためにGolangでアプリケーションを開発し、レコードごとにHTTPリクエストを行い、データベースを更新します。
これはすべて簡単です。しかし、私たちはPGBouncerを所定の位置に持っています。 PGBouncerの設定は、準備されたステートメントをサポートしていないようなものです。準備済みステートメントですべてのクエリを静かにラップします。 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
}
.
(HHMM、小さなインデントを投げているようです) お尻あなたは私がトランザクションを閉じないBNUTを起動しているのを見ることができます。これにより、選択がすべての選択が「トランザクションのアイドル」状態に残っているもののPG側に問題が発生します。
tx.commit()とtx.rollback()を試してみました、そしてどちらの場合もエラーが発生しました:
"unknown response for simple query '3'"
.
または
"unknown response for simple query 'D'"
.
ho取引を行くのに成功しましたか?私は私がドライバーライブラリのlib / pqに切り替えることを可能にするように私たちのpgbouncer.iniを更新することを望んでいますが、それが直接この問題を助けるかどうかはわかりません。
だから、TXオブジェクトを正しく閉じるのか、あるいはフードの下に準備されたステートメントを使用しないようにする方法は?
感謝 ネイサン
物事を少し上げようとしました:
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'
.
しかし、私はこれが2回目のSELECTステートメントを試しているときにあることを指摘してください。このアプリケーションはバッチを選択し、それを対処してから、後続のバッチを選択します。このエラーは2番目の選択で発生します。最初の選択の問題はありません。
解決
これを襲う他の誰かがこれを解決しました。
コードが上記の通話コード(図示せず)に行オブジェクトを返していました。行が読まれる前にトランザクションを閉じることは問題の原因であるようです。私はなぜ私はなぜ理解していませんので、あなたがするならば明らかにしてください。
今度は行とトランザクションオブジェクトの両方を返します。それから私がすべての行を読んだとき私はトランザクションをロールバックします。これはすべての作業を続けます。
感謝 ネイサン
他のヒント
tx.queryは、結果セットのカーソルであるSQL.ROWSのインスタンスを返します。このカーソルを繰り返している間、データは必ずしも取得されていません。カーソルを繰り返している間、トランザクションは開いたままになる必要があります。
これが、トランザクションが閉じられたらカーソルを繰り返すことができなかった理由です。