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?
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!