一文讀懂 MongoDB驅動程式 API
回撥API和核心API
回撥 API :
-
啟動一個事務,執行指定的操作,並提交(或出錯時中止)。
-
自動包含
"TransientTransactionError"
和"UnknownTransactionCommitResult"
的錯誤處理邏輯。
核心 API :
-
需要顯式呼叫來啟動事務並提交事務。
-
不包含 "TransientTransactionError" 和 "UnknownTransactionCommitResult" 的錯誤處理邏輯,而是為這些錯誤提供了包含自定義錯誤處理的靈活性。
回撥API
回撥 API 包含以下邏輯:
-
如果事務遇到
"TransientTransactionError"
,則作為一個整體重試事務。 -
如果提交遇到
"UnknownTransactionCommitResult"
,則重新這個提交操作。
示例:
該示例使用新的回撥 API 來處理事務,它啟動事務、執行指定的操作並提交(或在出錯時中止)。新的回撥 API 包
含
"TransientTransactionError"
或
"UnknownTransactionCommitResult"
提交錯誤的重試邏輯。
重要
-
推薦。 使用針對 MongoDB 部署版本更新的 MongoDB 驅動程式。對於 MongoDB 4.2 部署(副本集和分片叢集)上的事務,客戶端 必須使用為 MongoDB 4.2 更新的 MongoDB 驅動程式。
-
使用驅動程式時,事務中的每個操作 必須與會話相關聯(即將會話傳遞給每個操作)。
-
在 MongoDB 4.2 及更早版本中,你無法在事務中建立集合。如果在事務內部執行,導致文件插入的寫操作(例如
insert
或帶有upsert: true
的更新操作)必須在 已有的 集合上執行。 -
從 MongoDB 4.4 開始,你可以隱式或顯式地在事務中建立集合。但是,你比須使用針對 4.4 更新的 MongoDB 驅動程式。有關詳細資訊,請參閱 在事務中建立集合和索引 。
// WithTransactionExample is an example of using the Session.WithTransaction function.
func WithTransactionExample() {
ctx := context.Background()
// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
// uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl"
// For a sharded cluster, connect to the mongos instances; e.g.
// uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/"
var uri string
clientOpts := options.Client().ApplyURI(uri)
client, err := mongo.Connect(ctx, clientOpts)
if err != nil {
panic(err)
}
defer func() { _ = client.Disconnect(ctx) }()
// Prereq: Create collections.
wcMajority := writeconcern.New(writeconcern.WMajority(), writeconcern.WTimeout(1*time.Second))
wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts)
barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts)
// Step 1: Define the callback that specifies the sequence of operations to perform inside the transaction.
callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
// Important: You must pass sessCtx as the Context parameter to the operations for them to be executed in the
// transaction.
if _, err := fooColl.InsertOne(sessCtx, bson.D{{"abc", 1}}); err != nil {
return nil, err
}
if _, err := barColl.InsertOne(sessCtx, bson.D{{"xyz", 999}}); err != nil {
return nil, err
}
return nil, nil
}
// Step 2: Start a session and run the callback using WithTransaction.
session, err := client.StartSession()
if err != nil {
panic(err)
}
defer session.EndSession(ctx)
result, err := session.WithTransaction(ctx, callback)
if err != nil {
panic(err)
}
fmt.Printf("result: %v\n", result)
}
核心API
核心事務 API 不包含標記錯誤的重試邏輯:
-
"TransientTransactionError"
。如果事務中的操作返回標記為"TransientTransactionError"
的錯誤,則事務會被作為一個整體進行重試。 -
"UnknownTransactionCommitResult"
。如果提交返回標記為"UnknownTransactionCommitResult"
的錯誤,提交會被重試。為了處理
"UnknownTransactionCommitResult"
,應用程式應該明確地包含錯誤的重試邏輯。
示例:
runTransactionWithRetry := func (sctx mongo.SessionContext, txnFn func(mongo.SessionContext) error) error {
for {
err := txnFn(sctx) // Performs transaction.
if err == nil {
return nil
}
log.Println( "Transaction aborted. Caught exception during transaction.")
// If transient error, retry the whole transaction
if cmdErr, ok := err.(mongo.CommandError); ok && cmdErr.HasErrorLabel( "TransientTransactionError") {
log.Println( "TransientTransactionError, retrying transaction...")
continue
}
return err
}
}
commitWithRetry := func (sctx mongo.SessionContext) error {
for {
err := sctx.CommitTransaction(sctx)
switch e := err.( type) {
case nil:
log.Println( "Transaction committed.")
return nil
case mongo.CommandError:
// Can retry commit
if e.HasErrorLabel( "UnknownTransactionCommitResult") {
log.Println( "UnknownTransactionCommitResult, retrying commit operation...")
continue
}
log.Println( "Error during commit...")
return e
default:
log.Println( "Error during commit...")
return e
}
}
}
// Updates two collections in a transaction.
updateEmployeeInfo := func (sctx mongo.SessionContext) error {
employees := client.Database( "hr").Collection( "employees")
events := client.Database( "reporting").Collection( "events")
err := sctx.StartTransaction(options.Transaction().
SetReadConcern(readconcern.Snapshot()).
SetWriteConcern(writeconcern.New(writeconcern.WMajority())),
)
if err != nil {
return err
}
_, err = employees.UpdateOne(sctx, bson.D{{ "employee", 3}}, bson.D{{ "$set", bson.D{{ "status", "Inactive"}}}})
if err != nil {
sctx.AbortTransaction(sctx)
log.Println( "caught exception during transaction, aborting.")
return err
}
_, err = events.InsertOne(sctx, bson.D{{ "employee", 3}, { "status", bson.D{{ "new", "Inactive"}, { "old", "Active"}}}})
if err != nil {
sctx.AbortTransaction(sctx)
log.Println( "caught exception during transaction, aborting.")
return err
}
return commitWithRetry(sctx)
}
return client.UseSessionWithOptions(
ctx, options.Session().SetDefaultReadPreference(readpref.Primary()),
func (sctx mongo.SessionContext) error {
return runTransactionWithRetry(sctx, updateEmployeeInfo)
},
)
}
驅動程式版本
對於 MongoDB 4.2 部署(副本集和分片叢集)上的事務 ,客戶端 必須使用為 MongoDB 4.2 更新的 MongoDB 驅動程式:
C 1.15.0 C# 2.9.0 Go 1.1 | Java 3.11.0 Node 3.3.0 Perl 2.2.0 | Python 3.9.0 Ruby 2.10.0 Scala 2.7.0 |
---|---|---|
|
|
|
對於 MongoDB 4.0 副本集上的事務,客戶端需要為 MongoDB 4.0 或更高版本更新 MongoDB 驅動程式。
Java 3.8.0Python 3.7.0C 1.11.0 | C# 2.7Node 3.1.0Ruby 2.6.0 | Perl 2.0.0PHP (PHPC) 1.5.0Scala 2.4.0 |
---|---|---|
|
|
|
"TransientTransactionError"
無論
retryWrites
的值是多少,事務內部的單個寫操作都不可重試。如果操作遇到一個錯誤
與標籤相關
"TransientTransactionError"
,比如當主節點降級,事務會作為一個整體被重試。
-
回撥 API 包含了
"TransientTransactionError"
的重試邏輯。 -
核心事務 API 不包含
"TransientTransactionError"
的重試邏輯。為了處理"TransientTransactionError"
,應用程式應該明確地包含錯誤的重試邏輯。
"UnknownTransactionCommitResult"
提交操作是
可重試的寫操作
。如果提交操作遇到錯誤,無論
retryWrites
的值是多少,MongoDB 驅動程式都會重試提交。
如果提交操作遇到標記為
"UnknownTransactionCommitResult"
的錯誤,提交可以被重試。
-
回撥 API 包含了
"UnknownTransactionCommitResult"
的重試邏輯。 -
核心事務 API 不包含
"UnknownTransactionCommitResult"
的重試邏輯。為了處理"UnknownTransactionCommitResult"
,應用程式應該明確地包含錯誤的重試邏輯。
驅動程式版本錯誤
Error Code | Error Message |
---|---|
251 |
cannot continue txnId -1 for session ... with txnId 1 |
50940 |
cannot commit with no participants |
對於 MongoDB 4.2 部署(副本集和分片叢集)上的事務,使用為 MongoDB 4.2 更新的 MongoDB 驅動程式。
附加資訊
mongo Shell 示例
mongo
shell 方法可用於事務:註釋
mongo
shell 示例為了簡單起見省略了重試邏輯和強大的錯誤處理。有關在應用程式中包含事務的更實際示例,請參閱
事務錯誤處理
。
// Create collections:
db.getSiblingDB( "mydb1").foo.insert( { abc: 0}, { writeConcern: { w: "majority", wtimeout: 2000 } } );
db.getSiblingDB( "mydb2").bar.insert( { xyz: 0}, { writeConcern: { w: "majority", wtimeout: 2000 } } );
// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
coll1 = session.getDatabase( "mydb1").foo;
coll2 = session.getDatabase( "mydb2").bar;
// Start a transaction
session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } );
// Operations inside the transaction
try {
coll1.insertOne( { abc: 1 } );
coll2.insertOne( { xyz: 999 } );
} catch (error) {
// Abort transaction on error
session.abortTransaction();
throw error;
}
// Commit the transaction using write concern set at transaction start
session.commitTransaction();
session.endSession();
原文連結:
現階段對開源分散式資料庫、雲端計算等領域有很大興趣;平時喜歡打羽毛球、看電影等。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69961190/viewspace-2869418/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一文讀懂微搭低程式碼
- 一文讀懂mavenMaven
- 一文讀懂Android程式及TCP動態心跳保活AndroidTCP
- 一文讀懂Java中的動態代理Java
- 一文讀懂微核心
- 一文讀懂特徵工程特徵工程
- 一文讀懂動態規劃演算法動態規劃演算法
- 一文讀懂支付系統
- 一文讀懂前端快取前端快取
- 一文讀懂野指標指標
- 一文讀懂“負載均衡”負載
- 一文讀懂web組態Web
- 一文讀懂層次聚類(Python程式碼)聚類Python
- [實戰] 使用 MongoDB Go 驅動與 Iris 構建 RESTful APIMongoDBRESTAPI
- 【智慧物流】一文讀懂自動化立體倉庫
- 一文讀懂git核心工作原理Git
- 一文讀懂:GBDT梯度提升梯度
- 一文讀懂Kafka副本機制Kafka
- JVM(2)--一文讀懂垃圾回收JVM
- 一文讀懂Spring整合RedisSpringRedis
- 【Flutter】一文讀懂混入類MixinFlutter
- 一文讀懂Go Http Server原理GoHTTPServer
- 一文讓你迅速讀懂ServerlessServer
- 一文讀懂系列-JVM垃圾收集JVM
- 一文讀懂「Attention is All You Need」| 附程式碼實現
- 一文讀懂H5移動開發除錯技巧H5移動開發除錯
- Log新增MongoDB驅動2MongoDB
- 一文讀懂 | AI技術如何驅動企業供應鏈智慧化,賦能企業降本增效?AI
- 一文讀懂BeanFactory和FactoryBean區別Bean
- 一文讀懂 Redis 分散式部署方案Redis分散式
- 一文讀懂JAVA多執行緒Java執行緒
- 一文讀懂MySQL複製機制MySql
- 一文讀懂容器儲存介面 CSI
- 告別DNS劫持,一文讀懂DoHDNS
- 一文讀懂機器學習中的模型偏差機器學習模型
- 一文讀懂瀏覽器快取瀏覽器快取
- 一文讀懂Apache Flink技術Apache
- 一文讀懂 Handler 機制全家桶