Docs Menu
Docs Home
/ /

Transacciones y Sesiones

En esta guía, aprenderá a usar Mongoid para realizar transacciones. Las transacciones permiten realizar una serie de operaciones que modifican los datos solo si se confirma la transacción completa. Si alguna operación de la transacción no se realiza correctamente, el controlador la detiene y descarta todos los cambios de datos antes de que sean visibles. Esta función se denomina atomicidad.

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

Las sesiones permiten ejecutar operaciones en una transacción compatible con ACID que cumple con las expectativas de atomicidad, consistencia, aislamiento y durabilidad. MongoDB garantiza que los datos involucrados en las operaciones de transacción se mantengan consistentes, incluso si las operaciones presentan errores inesperados.

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: Debe gestionar el ciclo de vida de la transacción. Puede usar esta API en Mongoid v6.4 y versiones posteriores.

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.

Puede usar la API de Transacciones de Alto Nivel para gestionar internamente el ciclo de vida de su transacción. Esta API confirma o finaliza la transacción e incorpora lógica de gestión de errores.

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

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

  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 invoca cualquier after_commit devolución de llamada para todos los objetos modificados dentro de la transacción. Si se produce un error y la transacción se revierte, Mongoid invoca cualquier after_rollback devolución de llamada para todos los objetos modificados dentro de la transacción. Para obtener más información sobre estas devoluciones de llamada y su comportamiento, consulte la sección "Devoluciones de llamada" 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 múltiples 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

Solo las operaciones del mismo cliente entran en el ámbito de una transacción, ya que cada transacción está asociada a un cliente específico. Asegúrese de utilizar objetos del mismo cliente dentro del bloque de 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

Cuando llama 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 en los datos. Mongoid muestra todas las excepciones excepto la excepción Mongoid::Errors::Rollback. Puede generar esta excepción en su aplicación para finalizar la transacción explícitamente sin que se le devuelva la excepción. Por ejemplo, podría implementar esta excepción de transacción para finalizar una transacción cuando no se cumple una condición determinada, 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 se confirma la transacción si el objeto fue modificado dentro de la transacción.

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

La devolución de llamada after_commit se activa solo después de que todas las demás se hayan ejecutado correctamente. Por lo tanto, si un objeto se modifica fuera de una transacción, es posible que persista, pero la devolución de llamada after_commit no se active. Esto podría ocurrir, por ejemplo, si Mongoid generara una excepción en la devolución de llamada after_save, ya que esta debe completarse correctamente 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ía para personalizar devoluciones de llamadas para modelos de datos.

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, puede iniciar una transacción llamando al método start_transaction en una sesión. Al usar esta API, debe confirmar o finalizar la transacción manualmente. Puede usar los métodos commit_transaction y abort_transaction en la instancia de sesión para administrar 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 de 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 finaliza e incluye una transacción abierta, la transacción finaliza automáticamente.

Puede reintentar la confirmación de la transacción si falla inicialmente. El siguiente ejemplo muestra cómo reintentar la transacción cuando Mongoid genera 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 realizar operaciones dentro de una transacción, se debe usar el mismo cliente en el que se inició la sesión. De forma predeterminada, todas las operaciones se realizan con el cliente predeterminado.

Para utilizar explícitamente un cliente diferente, utilice 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 forma similar a como se realiza una transacción. Puedes llamar al método with_session en una clase de modelo o en una instancia de un modelo y realizar operaciones en un bloque. Todas las operaciones del bloque se realizarán en el contexto de una sola sesión.

Se aplican las siguientes limitaciones al utilizar sesiones:

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

  • No se pueden anidar sesiones. Por ejemplo, no se puede llamar al método with_session de una clase de modelo dentro del bloque pasado al método with_session de otra clase de modelo. El siguiente código muestra una sesión anidada que genera 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 modelo utilizadas en el bloque de sesión deben usar el mismo cliente controlador. Por ejemplo, si especifica un cliente distinto para un modelo utilizado en el bloque que el del modelo o la instancia en la que se invocó with_session, Mongoid devuelve 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 y 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, consulte los detalles del constructor de la clase Session en la documentación de la API del controlador Ruby.

Alternativamente, puede utilizar el método with_session en una instancia de un 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 una instancia de Book, 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 obtener más información sobre las transacciones, consulte Transacciones en el manual del servidor.

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

Volver

Texto de query

En esta página