Maison > développement back-end > Golang > le corps du texte

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

WBOY
Libérer: 2024-02-06 10:12:08
avant
431 Les gens l'ont consulté

在发生错误时省略 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)
Copier après la connexion

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
}
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!