Maison >développement back-end >Golang >Est-ce une bonne pratique d'omettre la restauration des transactions MongoDB en cas d'erreur ?

Est-ce une bonne pratique d'omettre la restauration des transactions MongoDB en cas d'erreur ?

WBOY
WBOYavant
2024-02-06 10:12:08473parcourir

在发生错误时省略 mongodb 事务回滚是一个好习惯吗

Contenu de la question

J'utilise le pilote Golanggo.mongodb.org/mongo-driver/mongo pour apprendre les transactions MongoDB. Je suis ceci donc répondez et cet exemple sur github.

Exemple de code donné par @simagix :

if session, err = client.StartSession(); err != nil {
    t.Fatal(err)
}
if err = session.StartTransaction(); err != nil {
    t.Fatal(err)
}
if err = mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error {
    if result, err = collection.UpdateOne(sc, bson.M{"_id": id}, update); err != nil {
        t.Fatal(err)
    }
    if result.MatchedCount != 1 || result.ModifiedCount != 1 {
        t.Fatal("replace failed, expected 1 but got", result.MatchedCount)
    }

    // more interrelated operations ...

    if err = session.CommitTransaction(sc); err != nil {
        t.Fatal(err)
    }
    return nil
}); err != nil {
    t.Fatal(err)
}
session.EndSession(ctx)

Dans les deux exemples, ils ne seront pas annulés si une erreur se produit. Je sais que c'est un exemple de démonstration. Mais quand je fais la même chose dans le code, ça marche bien.

Est-il possible d'omettre la restauration lorsqu'une erreur se produit (le pilote la gère-t-il) ? Ou est-ce que j'ai raté quelque chose ?


La bonne réponse


mongo.withsession() ne suppose aucune transaction active, elle permet "seulement" d'exécuter des rappels dans le cadre d'une session donnée. Par conséquent, si vous souhaitez qu'il soit exécuté dans le cadre de la transaction initiée, vous devez gérer la validation et l'abandonner vous-même. Cela permet un contrôle plus fin.

Cependant, si vous envisagez d'exécuter le rappel en tant que transaction, utilisez session.withtransaction() car il gère les transactions et leur cycle de vie de manière transparente : il crée la transaction et la valide ou l'abandonne en fonction de l'erreur renvoyée par le rappel. En tant que fonctionnalité supplémentaire, il peut également gérer les tentatives. Comme le souligne également sa documentation :

Si le rappel échoue, le conducteur appellera aborttransaction.

Voici un exemple simple de la façon d'exécuter correctement les rappels au sein d'une transaction :

var docToInsert, idToUpdate, updateDoc any

func doInTransactionExample(ctx context.Context, client *mongo.Client) error {
    sess, err := client.StartSession(options.Session().SetDefaultReadConcern(readconcern.Majority()))
    if err != nil {
        return fmt.Errorf("client.StartSession() error: %w", err)
    }
    defer sess.EndSession(ctx)

    result, err := sess.WithTransaction(
        ctx,
        func(sessCtx mongo.SessionContext) (any, error) {
            // sessCtx must be used as context.Context for all operations to be run in the transaction.
            var ctx context.Context = sessCtx // Shadow ctx on purpose!

            c := client.Database("foo").Collection("bar")

            // Insert example
            if _, err := c.InsertOne(ctx, docToInsert); err != nil {
                return nil, fmt.Errorf("InsertOne() failed: %w", err)
            }

            // Update example
            if ur, err := c.UpdateByID(ctx, idToUpdate, updateDoc); err != nil {
                return nil, fmt.Errorf("UpdateByID() failed: %w", err)
            } else {
                if ur.MatchedCount == 0 {
                    return nil, fmt.Errorf("UpdateByID() failed: %w", mongo.ErrNoDocuments)
                }
            }

            return "arbitrary-result-to-return", nil
        },
        options.Transaction().SetReadPreference(readpref.PrimaryPreferred()),
    )

    if err != nil {
        return fmt.Errorf("sess.WithTransaction() error: %w", err)
    }

    _ = result // Not using result

    return nil
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer