.. _transactions: ************ Transactions ************ .. default-domain:: mongodb .. contents:: On this page :local: :backlinks: none :depth: 2 :class: singlecol Version 4.0 of the MongoDB server introduces `multi-document transactions `_. (Updates to multiple fields within a single document are atomic in all versions of MongoDB). Transactions require Mongoid version 6.4 or higher and Ruby driver version 2.6 or higher. Using Transactions ================== In order to start a transaction, the application must have a :ref:`session `. A transaction can be started by calling the ``start_transaction`` method on a session, which can be obtained by calling the ``with_session`` method on either a model class or instance: .. code-block:: ruby 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 It is also possible to specify read concern, write concern and read preference when starting a transaction: .. code-block:: ruby Person.with_session do |session| session.start_transaction( read_concern: {level: :majority}, write_concern: {w: 3}, read: {mode: :primary}) end A transaction may be committed or aborted. The corresponding methods to do so are ``commit_transaction`` and ``abort_transaction``, again on the session instance: .. code-block:: ruby Person.with_session do |session| session.commit_transaction end Person.with_session do |session| session.abort_transaction end If a session ends with an open transaction, `the transaction is aborted `_. The transaction commit `can be retried `_ if it fails. Here is the Ruby code to do so: .. code-block:: ruby begin session.commit_transaction rescue Mongo::Error => e if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL) retry else raise end end Note that in order to perform operations within the transaction, operations must use the same client that the session was initiated on. By default, all operations will be done on the default client: .. code-block:: ruby 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 To explicitly use a different client, use the ``with`` method: .. code-block:: ruby 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