4

技術詳細

  • バージョン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 番目の選択で発生します。最初の選択に問題はありません。

4

2 に答える 2