我正在使用golang驅動程式go.mongodb.org/mongo-driver/mongo
學習mongodb交易。我正在 github 上關注這個 so 答案和這個示例。
@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)
在這兩個範例中,如果發生錯誤,它們都不會回滾。我知道這是一個演示樣本。但是當我在程式碼中執行相同操作時,它工作得很好。
在發生錯誤時是否可以省略回滾(驅動程式是否處理它)?還是我錯過了什麼?
mongo.withsession()
確實不假設任何活動事務,它「僅」有幫助於在給定會話下運行回調。因此,如果您希望它作為啟動事務的一部分執行,您應該自己處理提交和中止。這樣可以進行更精細的控制。
但是,如果您打算將回調作為事務運行,則使用session.withtransaction()
因為它以透明的方式處理事務及其生命週期:它創建事務並根據回調返回的錯誤提交或中止它。作為額外的功能,它還可以處理重試。正如其文件也指出的那樣:
如果回呼失敗,驅動程式將呼叫aborttransaction。
這是一個如何在交易中正確執行回呼的簡單範例:
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 }
以上是在發生錯誤時省略 mongodb 事務回滾是個好習慣嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!