トランザクション
MongoDB サーバーのバージョン4.0では、 マルチドキュメントトランザクションが導入されています。 (単一のドキュメント内の複数のフィールドの更新は、MongoDB のすべてのバージョンでアトミックです)。 トランザクションには非スタンドアロンの MongoDB トポロジーと Ruby ドライバー バージョン2.6以上が必要です。 高レベルのトランザクション API には Mongoid バージョン9.0以上が必要で、下位レベルの API には Mongoid バージョン6が必要です。 4以上
トランザクションの使用
高レベル API
トランザクションは、Mongoid ドキュメント クラスのインスタンス、Mongoid ドキュメント クラス、またはMongoid
モジュールで transaction
メソッドを呼び出すことで開始できます。
Band.transaction do Band.create(title: 'Led Zeppelin') end band = Band.create(title: 'Deep Purple') band.transaction do band.active = false band.save! end Mongoid.transaction do band.destroy end
transaction
メソッドが呼び出されると、Mongoid は次の処理を実行します。
は、
transaction
メソッド呼び出しの受信者が使用するクライアント上でセッションを作成します。セッションでトランザクションを開始する
指定されたブロックを実行し、
ブロック内で例外が発生しない場合はトランザクションをコミットします。
トランザクション内で変更されたすべてのオブジェクトに対して
after_commit
コールバックを呼び出す
ブロックで例外が発生した場合はトランザクションを中止します。
トランザクション内で変更されたすべてのオブジェクトに対して
after_rollback
コールバックを呼び出す
セッションを閉じます
注意
トランザクションは特定のクライアントに関連付けられているため、同じクライアントでの _only_ 操作はトランザクションの範囲内になります。 したがって、 transaction
メソッド ブロック内では同じクライアントを使用するオブジェクトのみを使用することをお勧めします。
class Author include Mongoid::Document store_in client: :encrypted_client end class User include Mongoid::Document store_in client: :encrypted_client end class Article include Mongoid::Document # This class uses the :default client end # Transaction is started on the :encrypted_client Author.transaction do # This operation uses the same client, so it is in the transaction Author.create! # This operation also uses the same client, so it is in the transaction User.create! # This operation uses a different client, so it is NOT in the transaction Article.create! end
注意
Mongoid
モジュールでtransaction
メソッドが呼び出されると、 :default
クライアントを使用してトランザクションが作成されます。
トランザクションの中止
transaction
メソッド ブロック内で発生した例外はトランザクションを中止します。 通常、発生した例外は に渡されます。ただし、 Mongoid::Errors::Rollback
は除きます。 例外を渡しずにトランザクションを明示的に中止する場合は、このエラーが発生します。
コールバック
Transaction API には、 after_commit
とafter_rollback
の 2 つの新しいコールバックが導入されています。
after_commit
コールバックは、作成、保存、または破棄されたオブジェクトに対してトリガーされます。
トランザクション内でオブジェクトが変更された場合は、トランザクションがコミットされた後。
オブジェクトがトランザクション外で変更された場合に、オブジェクトが保持された後。
注意
いずれの場合も、 after_commit
コールバックは、他のすべてのコールバックが正常に実行された後にのみトリガーされます。 したがって、トランザクションなしでオブジェクトが変更されている場合、オブジェクトは永続化されていたが、 after_commit
コールバックはトリガーされなかった可能性があります(たとえば、 after_save
コールバックで例外が発生した)。
after_rollback
コールバックは、トランザクションが中止された場合にトランザクション内で作成、保存、または破棄されたオブジェクトに対してトリガーされます。 after_rollback
はトランザクションなしではトリガーされません。
下位レベル API
トランザクションを開始するには、アプリケーションにセッションが必要です。
トランザクションはセッションでstart_transaction
メソッドを呼び出すことで開始できます。このトランザクションは、モデル クラスまたは インスタンスのいずれかでwith_session
メソッドを呼び出すことで取得できます。
class Person include Mongoid::Document end Person.with_session do |session| session.start_transaction end person = Person.new person.with_session do |session| session.start_transaction end
トランザクションを開始するときに、読み取り保証、書込み保証、および読み込み設定(read preference)を指定することもできます。
Person.with_session do |session| session.start_transaction( read_concern: {level: :majority}, write_concern: {w: 3}, read: {mode: :primary}) end
トランザクションはコミットまたは中止される可能性があります。 また、セッション インスタンスでは、それに対応するメソッドもcommit_transaction
とabort_transaction
です。
Person.with_session do |session| session.commit_transaction end Person.with_session do |session| session.abort_transaction end
オープン トランザクションでセッションが終了すると、そのトランザクションは 中止されます 。
トランザクションのコミットは失敗した場合に再試行できます 。 以下は、そのための Ruby コードです。
begin session.commit_transaction rescue Mongo::Error => e if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL) retry else raise end end
トランザクション内で操作を実行するには、セッションが開始されたのと同じクライアントを使用する必要があることに注意してください。 デフォルトでは、すべての操作はデフォルトのクライアントで実行されます。
class Person include Mongoid::Document end class Post include Mongoid::Document end Person.with_session do |s| s.start_transaction Person.create! Person.create! Post.create! s.commit_transaction end
別のクライアントを明示的に使用するには、 with
メソッドを使用します。
Post.with(client: :other) do Person.with(client: :other) do Person.with_session do |s| s.start_transaction Person.create! Person.create! Post.create! s.commit_transaction end end end