Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Transacciones y Sesiones

En esta guía, puedes aprender a usar Mongoid para realizar transacciones. Las transacciones te permiten realizar una serie de operaciones que cambian los datos solo si toda la transacción se completa. Si alguna operación en la transacción no tuvo éxito, el controlador detiene la transacción y descarta todos los cambios de datos antes de que lleguen a ser visibles. Esta funcionalidad se llama atomicidad.

En MongoDB, las transacciones se ejecutan dentro de sesiones lógicas. Una sesión es una agrupación de operaciones de lectura o escritura relacionadas que se desean ejecutar secuencialmente. Las sesiones permiten la coherencia causal para un grupo de operaciones, lo que significa que todos los procesos en tu aplicación están de acuerdo sobre el orden de las operaciones relacionadas causalmente.

Las sesiones le permiten ejecutar operaciones en una transacción compatibles con ACID que cumplen con las expectativas de atomicidad, coherencia, aislamiento y durabilidad. MongoDB garantiza que los datos involucrados en las operaciones de tus transacciones permanezcan coherentes, incluso si las operaciones encuentran errores imprevistos.

En Mongoid, puedes realizar transacciones utilizando cualquiera de las siguientes API:

  • API de transacciones de alto nivel: Mongoid gestiona el ciclo de vida de las transacciones. Puede usar esta API en Mongoid v9.0 y versiones posteriores.

  • API de Transacciones de Bajo Nivel: Debes gestionar el ciclo de vida de la transacción. Puedes utilizar esta API en Mongoid v6.4 o posterior.

La sección API de sesión describe cómo realizar cambios en tus datos desde dentro de una sesión sin realizar una transacción.

Puedes usar la API de Transacciones de Alto Nivel para gestionar internamente el ciclo de vida de tu transacción. Esta API o bien confirma tu transacción o la finaliza e incorpora lógica de manejo de errores.

Puedes comenzar una transacción llamando al transaction método en una instancia de un modelo, en la clase modelo o en un módulo Mongoid.

Cuando llamas al método transaction, Mongoid realiza las tareas siguientes:

  1. Crea una sesión en el cliente.

  2. Inicia una transacción en la sesión.

  3. Realiza los cambios de datos especificados.

  4. Confirma la transacción en la base de datos si no se producen errores o finaliza la transacción si hay un error.

  5. Cierra la sesión.

Si su transacción se confirma, Mongoid llama a cualquier after_commit función de retorno para todos los objetos modificados dentro de la transacción. Si ocurre un error y la transacción se revierte, Mongoid llama a cualquier after_rollback función de retorno para todos los objetos modificados dentro de la transacción. Para aprender más sobre estas funciones de retorno y su comportamiento, consulta la sección funciones de retorno de esta guía.

Este ejemplo utiliza los siguientes modelos para representar documentos que describen libros y películas:

class Book
include Mongoid::Document
field :title, type: String
field :author, type: String
field :length, type: Integer
end
class Film
include Mongoid::Document
field :title, type: String
field :year, type: Integer
end

El siguiente código demuestra cómo realizar una transacción en diferentes objetos para cambiar datos en varias colecciones:

# Starts a transaction from the model class
Book.transaction do
# Saves new Book and Film instances to MongoDB
Book.create(title: 'Covert Joy', author: 'Clarice Lispector')
Film.create(title: 'Nostalgia', year: 1983)
end
# Starts a transaction from an instance of Book
book = Book.create(title: 'Sula', author: 'Toni Morrison')
book.transaction do
# Saves a new field value to the Book instance
book.length = 192
book.save!
end
# Starts a transaction from the Mongoid instance
Mongoid.transaction do
# Deletes the Book instance in MongoDB
book.destroy
end

Sólo las operaciones sobre el mismo cliente están en el ámbito de una transacción, porque cada transacción está vinculada a un cliente específico. Asegúrese de utilizar objetos del mismo cliente dentro del bloque del método de transacción.

El siguiente ejemplo define clases modelo que utilizan diferentes clientes y demuestra cómo se ejecutan las operaciones en función del cliente de origen:

# Defines a class by using the :default client
class Post
include Mongoid::Document
end
# Defines a class by using the :encrypted_client
class User
include Mongoid::Document
store_in client: :encrypted_client
end
# Starts a transaction on the :encrypted_client
User.transaction do
# Uses the same client, so the operation is in the transaction
User.create!
# Uses a different client, so it is *not* in the transaction
Post.create!
end

Nota

Al llamar al método transaction en el módulo Mongoid, Mongoid crea la transacción utilizando el cliente :default.

Cualquier excepción generada dentro del bloque del método de transacción finaliza la transacción y revierte los cambios de datos. Mongoid muestra todas las excepciones excepto la excepción Mongoid::Errors::Rollback. Puedes activar esta excepción en tu aplicación para finalizar explícitamente la transacción sin que la excepción se te devuelva. Por ejemplo, puedes implementar esta excepción de transacción para finalizar una transacción cuando no se cumple una determinada condición, pero sin generar un mensaje de excepción.

Esta API de transacción presenta las devoluciones de llamadas after_commit y after_rollback.

Mongoid activa la devolución de llamada after_commit para un objeto que se creó, guardó o eliminó en los siguientes casos:

  • Después de que la transacción se haya confirmado, si el objeto fue modificado dentro de la transacción.

  • Después de que el objeto se conserve si el objeto fue modificado fuera del bloque de transacción.

La after_commit función de retorno se activa solo después de que todas las demás funciones de retorno se completan con éxito. Por ende, si un objeto se modifica fuera de una transacción, es posible que luego se persista el objeto, pero no se dispare la función de retorno after_commit. Esto puede ocurrir, por ejemplo, si Mongoid lanza una excepción en el after_save función de retorno porque este función de retorno debe completarse con éxito para activar after_commit.

La devolución de llamada after_rollback se activa para un objeto creado, guardado o eliminado dentro de una transacción si esta no se realizó correctamente y se revirtieron los cambios. Mongoid nunca activa after_rollback fuera de una transacción.

Para obtener más información sobre las devoluciones de llamadas, consulte la Guíapara personalizar las funciones de devolución de llamada para modelos.

Al usar la API de bajo nivel, debe crear una sesión antes de iniciar una transacción. Puede crear una sesión llamando al método with_session en una clase de modelo o en una instancia de un modelo.

Luego, puedes iniciar una transacción llamando al método start_transaction en una sesión. Al utilizar esta API, debe comprometerse o finalizar manualmente la transacción. Puede usar los métodos commit_transaction y abort_transaction en la instancia de sesión para gestionar el ciclo de vida de la transacción.

Este ejemplo utiliza la API de transacciones de bajo nivel para realizar las siguientes acciones:

  1. Crea una sesión

  2. inicia una transacción

  3. Realiza operaciones sobre datos

  4. Confirma la transacción o la finaliza si hay errores

# Starts a session from the model class
Book.with_session do |session|
session.start_transaction
# Creates a Book
Book.create(title: 'Siddhartha', author: 'Hermann Hesse')
# Commits the transaction
session.commit_transaction
rescue StandardError
# Ends the transaction if there is an error
session.abort_transaction
end

Nota

Si una sesión termina e incluye una transacción abierta, la transacción finaliza automáticamente.

Puedes reintentar la confirmación de la transacción si inicialmente falla. El siguiente ejemplo demuestra cómo reintentar la transacción cuando Mongoid lanza la excepción UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL:

begin
session.commit_transaction
rescue Mongo::Error => e
if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
retry
else
raise
end
end

Puede especificar una preocupación de lectura, preocupación de escritura o preferencia de lectura al iniciar una transacción pasando opciones al método start_transaction:

session.start_transaction(
read_concern: {level: :majority},
write_concern: {w: 3},
read: {mode: :primary}
)

Para obtener más información sobre las opciones de transacción disponibles, consulte start_transaction en la documentación de la API del controlador Ruby.

Para efectuar operaciones dentro de una transacción, las operaciones deben usar el mismo cliente en el que se inició la sesión. De forma predeterminada, todas las operaciones se realizan utilizando el cliente por defecto.

Para utilizar explícitamente un cliente diferente, utiliza el método with:

# Specifies that the operation should use the "other" client instead of
# the default client
User.with(client: :other) do
Post.with(client: :other) do
Post.with_session do |session|
session.start_transaction
Post.create!
Post.create!
User.create!
session.commit_transaction
end
end
end

Puedes usar sesiones en Mongoid de manera similar a como puedes realizar una transacción. Puedes llamar al método with_session en una clase de modelo o en una instancia de un modelo y realizar algunas operaciones en un bloque. Todas las operaciones del bloque se realizarán en el contexto de una única sesión.

Se aplican las siguientes limitaciones al usar sesiones:

  • No se puede compartir una sesión entre hilos. Las sesiones no son seguras para subprocesos.

  • No puedes anidar sesiones. Por ejemplo, no se puede llamar al método with_session en una clase modelo dentro del bloque pasado al método with_session en otra clase modelo. El siguiente código demuestra una sesión anidada que resulta en un error:

    Book.with_session(causal_consistency: true) do
    # Nesting sessions results in errors
    Film.with_session(causal_consistency: true) do
    ...
    end
    end
  • Todas las clases e instancias de modelos utilizadas dentro del bloque de sesión deben utilizar el mismo cliente del controlador. Por ejemplo, si especificas un cliente diferente para un modelo utilizado en el bloque que los del modelo o instancia en la que llamaste with_session, Mongoid devolverá un error.

Puede utilizar el método with_session en una clase modelo y pasarle opciones de sesión para realizar un bloque de operaciones en el contexto de una sesión.

El siguiente código habilita la opción causal_consistency para garantizar el orden de las operaciones al crear una sesión en el modelo Book, luego realiza operaciones de datos:

Book.with_session(causal_consistency: true) do
Book.create!
book = Person.first
book.title = "Swann's Way"
book.save
end

Para obtener más información sobre las opciones de sesión disponibles, consulta los Detalles del constructor de la clase Session en la documentación de la API del driver Ruby.

Como alternativa, puedes usar el método with_session en una instancia de un modelo y pasarle opciones de sesión para ejecutar un bloque de operaciones en el contexto de una sesión.

El siguiente código habilita la opción causal_consistency para garantizar el orden de las operaciones al crear una sesión en una instancia de Book, y luego realiza operaciones de datos:

book = Book.new
book.with_session(causal_consistency: true) do
book.title = 'Catch-22'
book.save
book.sellers << Shop.create!
end

Para aprender más sobre transacciones, consulta Transacciones en el manual del Servidor.

Para obtener más información sobre cómo realizar operaciones CRUD, consulte la guía de operaciones CRUD.

Volver

Consultas asíncronas

En esta página