Saya menggunakan pemandu golanggo.mongodb.org/mongo-driver/mongo
untuk mempelajari transaksi mongodb. Saya mengikuti ini jadi jawapan dan contoh ini di github.
Contoh kod diberikan oleh @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)
Dalam kedua-dua contoh, mereka tidak akan berundur jika ralat berlaku. Saya tahu ini adalah contoh demo. Tetapi apabila saya melakukan perkara yang sama dalam kod, ia berfungsi dengan baik.
Adakah mungkin untuk mengetepikan rollback apabila ralat berlaku (adakah pemandu mengendalikannya)? Atau adakah saya kehilangan sesuatu?
mongo.withsession()
tidak menganggap sebarang transaksi aktif, ia "hanya" membantu menjalankan panggilan balik di bawah sesi tertentu. Oleh itu, jika anda mahu ia dilaksanakan sebagai sebahagian daripada urus niaga yang dimulakan, anda harus mengendalikan komit dan menggugurkan sendiri. Ini membolehkan kawalan yang lebih halus.
Walau bagaimanapun, jika anda bercadang untuk menjalankan panggilan balik sebagai transaksi, gunakan session.withtransaction()
kerana ia mengendalikan urus niaga dan kitaran hayatnya dengan cara yang telus: ia mencipta urus niaga dan melakukan atau membatalkannya berdasarkan ralat yang dikembalikan oleh panggilan balik. Sebagai ciri tambahan, ia juga boleh mengendalikan percubaan semula. Seperti yang ditunjukkan oleh dokumentasinya:
Jika panggilan balik gagal, pemandu akan memanggil aborttransaction.
Berikut ialah contoh mudah cara melaksanakan panggilan balik dengan betul dalam transaksi:
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 }
Atas ialah kandungan terperinci Adakah amalan yang baik untuk meninggalkan pengembalian transaksi mongodb apabila ralat?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!