Overview
このガイドでは、MongoDB Go Driver を使ってトランザクションを実行する方法を説明します。トランザクションを使用すると、トランザクションがコミットされるまでデータを変更しない一連の操作を実行できます。トランザクション内のいずれかの操作でエラーが返された場合、ドライバーはトランザクションをキャンセルし、変更が反映される前にすべてのデータ変更を破棄します。
MongoDB では、トランザクションは論理セッション内で実行されます。セッションは、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。セッションにより、一連の操作に対する因果整合性が有効になる、または ACID transaction 内で操作を実行できるようになります。MongoDBは、トランザクション操作で予期せぬエラーが発生した場合でも、その操作に関わるデータの一貫性が保たれることを保証します。
Go ドライバーを使用する場合、Client インスタンスから Session 型の新しいセッションを作成できます。毎回新しいクライアントをインスタンス化するのではなく、複数のセッションで同じクライアントとトランザクションを使用することを推奨します。
警告
Session は、それを作成した Client(または関連付けられたDatabase または Collection)でのみ使用します。Session と、異なる Client を使用すると、操作エラーが発生します。
警告
Session の実装は、複数の goroutine による同時使用では安全ではありません。
セッションメソッド
クライアントで StartSession() メソッドを使用してセッションを開始した後、返された Session によって提供されるメソッド セットを使用してセッション状態を変更できます。 次の表では、これらの方法について説明します。
方式 | 説明 |
|---|---|
| このセッションで、指定されたオプションで構成された新しいトランザクションを開始します。セッションで既にトランザクションが実行中の場合はエラーを返します。このメソッドの詳細については、サーバー マニュアルの「startTransaction() ページ」を参照してください。 |
| このセッションのアクティブなトランザクションを終了します。セッションにアクティブなトランザクションがない場合、またはトランザクションがコミットされたか、または終了した場合はエラーを返します。このメソッドの詳細については、サーバー マニュアルの abortTransaction() ページを参照してください。 |
| このセッションのアクティブなトランザクションをコミットします。セッションにアクティブなトランザクションがない場合、またはトランザクションが終了した場合はエラーを返します。このメソッドの詳細については、サーバー マニュアルの commitTransaction() ページを参照してください。
|
| このセッションでトランザクションを開始し、 |
| 既存のトランザクションを終了し、セッションを閉じます。 |
Sessionには、セッション プロパティを取得し、可変セッション プロパティを変更するメソッドもあります。 これらのメソッドの詳細については、 API ドキュメントを表示します。
セッションとトランザクションのオプション
セッションレベルおよびトランザクションレベルでオプションを設定し、ドライバーがトランザクションを実行する方法をカスタマイズできます。以下の手順では、特定の Session 内で実行されるすべてのトランザクションに対するオプションの設定方法を説明します。
TransactionOptionsインスタンスを作成します。指定されたセッションで実行されるすべてのトランザクションに対して、書込み保証 (write concern)、読み取り保証 (read concern)、読み込み設定 (read preference) などのオプションを指定できます。SetDefaultTransactionOptions()メソッドを呼び出し、TransactionOptionsインスタンスをパラメータとして渡して、SessionOptionsインスタンスを作成します。また、
SessionOptionsインスタンスで因果整合性などの他のセッションオプションを指定することも可能です。SessionOptionsインスタンスをclient.StartSession()メソッドに渡します。
次のコードは、セッションとトランザクションのオプションを指定し、これらのオプションを用いてセッションを作成します。
txnOpts := options.Transaction().SetReadConcern(readconcern.Majority()) sessOpts := options.Session().SetDefaultTransactionOptions(txnOpts) session, err := client.StartSession(sessOpts) if err != nil { return err }
注意
並列操作はサポートされていません
Go ドライバーは、1 つのトランザクション内で並列操作を実行することをサポートしていません。
アプリケーションが MongoDB Server v8.0 以降に接続されている場合、クライアントの一括書き込み機能を使用して、単一のトランザクション内で複数の名前空間に対して書き込み操作を実行できます。詳細については、『一括操作ガイド』のクライアント一括書き込みセクションを参照してください。
例
このセクションの例では、コレクションに挿入するドキュメントのデータモデルとして、次の Book 構造体を使用します。
type Book struct { Title string `bson:"title"` Author string `bson:"author"` }
次の例は、以下の手順でセッションを作成し、トランザクションを作成し、複数のドキュメント挿入操作をコミットする方法を示しています。
StartSession()メソッドを使用してクライアントからセッションを作成します。トランザクションを開始するには、
WithTransaction()メソッドを使用します。複数のドキュメントを挿入します。
WithTransaction()メソッドは挿入を実行し、トランザクションをコミットします。いずれかの操作でエラーが発生した場合、WithTransaction()がトランザクションのキャンセルを取り扱います。EndSession()メソッドを使用してトランザクションとセッションを閉じます。
wc := writeconcern.Majority() txnOptions := options.Transaction().SetWriteConcern(wc) // Starts a session on the client session, err := client.StartSession() if err != nil { panic(err) } // Defers ending the session after the transaction is committed or ended defer session.EndSession(context.TODO()) // Inserts multiple documents into a collection within a transaction, // then commits or ends the transaction result, err := session.WithTransaction(context.TODO(), func(ctx context.Context) (any, error) { result, err := coll.InsertMany(ctx, []any{ Book{Title: "The Bluest Eye", Author: "Toni Morrison"}, Book{Title: "Sula", Author: "Toni Morrison"}, Book{Title: "Song of Solomon", Author: "Toni Morrison"}, }) return result, err }, txnOptions)
手動トランザクションの例
トランザクションをさらに制御する必要がある場合は、トランザクションを手動で作成、コミット、および終了できます。この例では、次のアクションを実行する方法を示しています。
StartSession()メソッドを使用してクライアントからセッションを作成します。トランザクションを開始するには、
StartTransaction()メソッドを使用します。トランザクション内に複数のドキュメントを挿入します。
CommitTransaction()メソッドを使用してトランザクションをコミットします。EndSession()メソッドを使用してセッションを終了します。
wc := writeconcern.Majority() txnOptions := options.Transaction().SetWriteConcern(wc) // Starts a session on the client session, err := client.StartSession() if err != nil { panic(err) } // Defers ending the session after the transaction is committed or ended defer session.EndSession(context.TODO()) err = mongo.WithSession(context.TODO(), session, func(ctx context.Context) error { if err = session.StartTransaction(txnOptions); err != nil { return err } docs := []any{ Book{Title: "The Year of Magical Thinking", Author: "Joan Didion"}, Book{Title: "Play It As It Lays", Author: "Joan Didion"}, Book{Title: "The White Album", Author: "Joan Didion"}, } result, err := coll.InsertMany(ctx, docs) if err != nil { return err } if err = session.CommitTransaction(ctx); err != nil { return err } fmt.Println(result.InsertedIDs) return nil }) if err != nil { if err := session.AbortTransaction(context.TODO()); err != nil { panic(err) } panic(err) }
詳細情報
挿入操作の詳細については、 ドキュメントの挿入 の基礎ページを参照してください。
Go ドライバーで書込み保証 (write concern) を指定する方法の詳細については、「書込み保証 (write concern)」を参照してください。
Go Driver でセッションとトランザクションを使用する追加の例については、マルチドキュメント ACID トランザクションに関する開発者ブログ記事を参照してください。
API ドキュメント
このガイドで説明した型やメソッドの詳細については、次の API ドキュメントを参照してください。