Heim  >  Artikel  >  Backend-Entwicklung  >  Ist es eine gute Praxis, das Mongodb-Transaktions-Rollback im Fehlerfall wegzulassen?

Ist es eine gute Praxis, das Mongodb-Transaktions-Rollback im Fehlerfall wegzulassen?

WBOY
WBOYnach vorne
2024-02-06 10:12:08431Durchsuche

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

Frageninhalt

Ich verwende den Golang-Treibergo.mongodb.org/mongo-driver/mongo, um Mongodb-Transaktionen zu lernen. Ich folge dieser Antwort und diesem Beispiel auf Github.

Beispielcode von @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)

In beiden Beispielen erfolgt kein Rollback, wenn ein Fehler auftritt. Ich weiß, dass dies ein Demobeispiel ist. Aber wenn ich dasselbe im Code mache, funktioniert es gut.

Ist es möglich, das Rollback auszulassen, wenn ein Fehler auftritt (wird der Treiber damit umgehen)? Oder übersehe ich etwas?


Richtige Antwort


mongo.withsession() setzt keine aktiven Transaktionen voraus, es hilft „nur“, Rückrufe unter einer bestimmten Sitzung auszuführen. Wenn Sie also möchten, dass es als Teil der initiierten Transaktion ausgeführt wird, sollten Sie den Commit selbst durchführen und abbrechen. Dies ermöglicht eine feinere Steuerung.

Wenn Sie jedoch planen, den Rückruf als Transaktion auszuführen, verwenden Sie session.withtransaction(), da es Transaktionen und ihren Lebenszyklus auf transparente Weise behandelt: Es erstellt die Transaktion und schreibt sie fest oder bricht sie basierend auf dem vom Rückruf zurückgegebenen Fehler ab. Als zusätzliche Funktion sind auch Wiederholungsversuche möglich. Wie die Dokumentation auch hervorhebt:

Wenn der Rückruf fehlschlägt, ruft der Treiber aborttransaction auf.

Hier ist ein einfaches Beispiel, wie Rückrufe innerhalb einer Transaktion korrekt ausgeführt werden:

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
}

Das obige ist der detaillierte Inhalt vonIst es eine gute Praxis, das Mongodb-Transaktions-Rollback im Fehlerfall wegzulassen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen