Question

Détail technique

  • Go Version 1.2
  • Postrgres Library pour Go Bmizerany / PQ

Ce problème me rend fou et j'espère que quelqu'un sera capable d'aider.

J'ai développé une application à Golang pour lire des données à partir d'une base de données Postgres et pour chaque enregistrement, faites une demande HTTP, puis mettez à jour la base de données.

C'est tout simplement assez simple. Cependant, nous avons PGBouncer en place. La configuration que nous avons pour PGBouncer est telle qu'elle ne supporte pas les déclarations préparées. Allez silencieusement toutes les questions dans une déclaration préparée. Le chemin autour de cela pour PGBouncer est de mettre en place une transaction. C'est bien et bon pour des choses comme insertion / mise à jour / Supprimer.

Dans le cas de la déclaration SELECT, je l'enveloppe en transaction:

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, qui semble avoir jet d'indenter un peu) Ass vous pouvez voir que je commence Bnut ne fermez pas la transaction. Cela provoque un problème dans le côté PG des choses où chaque sélection est laissé dans un état 'inactif en transaction ".

J'ai essayé TX.COMMIT () et TX.Rollback () et dans les deux cas, je reçois des erreurs:

"unknown response for simple query '3'"

ou

"unknown response for simple query 'D'"

HO Fais-je avec succès la transaction en déplacement? J'espère obtenir notre pgbouncer.ini mis à jour pour me permettre de passer à lib / pq pour la bibliothèque de pilotes, mais je ne sais pas si cela aidera directement ce problème.

Alors, comment ferme l'objet TX correctement ou y a-t-il un moyen de forcer à ne pas utiliser de déclarations préparées sous la hotte?

merci Nathan

J'ai essayé de changer les choses un peu:

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
}

Ce que je vois dans les journaux avec ce code:

pq: unexpected describe rows response: '3'

Cependant, je devrais souligner que cela correspond à une instruction SELECT pour la deuxième fois. Cette application sélectionne un lot, y traite, puis sélectionne un lot ultérieur. Cette erreur se produit sur la seconde sélection. Il n'y a pas de problèmes avec le tout premier sélection.

Était-ce utile?

La solution

Pour quelqu'un d'autre qui frappe cela, j'ai résolu ceci.

Le code que j'avais renvoyé l'objet des rangées au code d'appel (non affiché) ci-dessus.La fermeture de la transaction avant que les rangées soient lues semblait être la cause du problème.Je ne comprends pas parfaitement pourquoi alors s'il vous plaît clarifier si vous le faites.

Maintenant, je retourne les lignes et l'objet de transaction.Ensuite, quand j'ai lu toutes les lignes, je retourne la transaction.Cela continue tout fonctionner.

merci Nathan

Autres conseils

TX.Quisery renvoie une instance de SQL.Rows, qui est un curseur sur le jeu de résultats.Les données n'ont pas nécessairement été récupérées pendant que vous itération de ce curseur.La transaction doit rester ouverte pendant que vous êtes itération du curseur.

C'est pourquoi vous ne pouviez plus itérer le curseur une fois la transaction fermée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top