Lectores como tú ayudan a apoyar a MUO. Cuando realiza una compra utilizando enlaces en nuestro sitio, podemos ganar una comisión de afiliado.

La creación de una aplicación web lista para producción requiere que se asegure de que sea segura y escalable.

Una de las cosas más importantes que debe saber sobre las bases de datos es el principio ACID, que significa atomicidad, consistencia, aislamiento y durabilidad. Las bases de datos relacionales como MySQL admiten transacciones ACID de forma nativa. Pero MongoDB es una base de datos NoSQL y no admite transacciones ACID de forma predeterminada.

Como programador, debe saber cómo introducir las propiedades ACID en sus bases de datos MongoDB.

¿Qué son las transacciones de base de datos?

Una transacción de base de datos es una secuencia de consultas u operaciones de base de datos que se ejecutan juntas como una unidad para completar una tarea.

Las transacciones de la base de datos se adhieren a los conceptos de las características ACID. Esto ayuda a garantizar que no se produzcan cambios a menos que todas las operaciones se realicen correctamente. También asegura que la base de datos sea consistente.

instagram viewer

Explicación de las propiedades ACID

Las cuatro propiedades que componen los principios ACID son:

  • Atomicidad es la propiedad que conceptualiza las transacciones como pequeñas unidades de un programa. Esto implica que todas las consultas se ejecutan correctamente o fallan juntas.
  • Consistencia establece que los registros de la base de datos deben permanecer consistentes antes y después de cada transacción.
  • Aislamiento asegura que, cuando varias transacciones se ejecutan simultáneamente, una no afecta a la otra.
  • Durabilidad se enfoca en las fallas o fallas del sistema. Garantiza que una transacción confirmada no se pierda en caso de falla del sistema. Esto puede implicar técnicas necesarias para restaurar datos de una copia de seguridad automáticamente una vez que el sistema vuelve a funcionar.

Cómo implementar transacciones de base de datos MongoDB en Node.js usando Mongoose

MongoDB se ha convertido en una tecnología de base de datos ampliamente utilizada a lo largo de los años debido a su naturaleza NoSQL y un modelo flexible basado en documentos. También le ofrece la posibilidad de organizar mejor sus datos y de forma más flexible que en SQL o bases de datos relacionales.

Para implementar transacciones de base de datos en MongoDB, puede considerar un escenario de muestra en una aplicación de listado de trabajos donde un usuario puede publicar, actualizar o eliminar un trabajo. Aquí hay un diseño de esquema de base de datos simple para esta aplicación:

Para continuar, esta sección requiere conocimientos básicos de programación Node.js y MongoDB.

Las transacciones no son compatibles con las instalaciones independientes de MongoDB. Necesitarás usar un Conjunto de réplicas de MongoDB o Clúster fragmentado de MongoDB para que las transacciones funcionen. Por lo tanto, la forma más fácil de usar transacciones es crear una instancia de MongoDB alojada en la nube (MongoDB Atlas). De forma predeterminada, cada instancia de la base de datos de Atlas es un conjunto de réplicas o un clúster fragmentado.

Después de configurar un proyecto Node.js y MongoDB en funcionamiento, puede configurar una conexión a una base de datos Mongo en Node.js. Si no lo ha hecho antes, instale mongoose ejecutando npm instalar mangosta en tu terminal.

importar mangosta de 'mangosta'

let MONGO_URL = proceso.env. MONGO_URL || 'su-mongo-base-de-datos-url';

dejar conexión;
constante conectarDb = asíncrono () => {
intentar {
esperar mangosta.conectar (MONGO_URL, {
useNewUrlParser: verdadero,
useUnifiedTopology: verdadero,
});

consola.log("CONECTADO A BASE DE DATOS");
conexión = mangosta.conexión;
} atrapar (Error) {
consola.error("¡FALLÓ LA CONEXIÓN DE LA BASE DE DATOS!");
consola.error(errar.mensaje);
proceso.salida(1); // cerrar la aplicación si falla la conexión a la base de datos
}
};

Debe almacenar la conexión en una variable para que pueda usarla para iniciar una transacción más adelante en el programa.

Puede implementar las colecciones de usuarios y trabajos de esta manera:

constante esquema de usuario = nuevo mangosta. Esquema({
nombre: Cadena,
correo electrónico: Cadena,
trabajos: [mangosta. Esquema. Tipos. Id. de objeto]
});

constante EsquemaTrabajo = nuevo mangosta. Esquema({
título: Cadena,
ubicación: Cadena,
salario: Cadena,
póster: mangosta.Esquema.Tipos.IdObjeto
});

const userCollection = mangosta.modelo('usuario', esquema de usuario);
const jobCollection = mangosta.modelo('trabajo', EsquemaTrabajo);

Puede escribir una función para agregar un usuario a la base de datos de esta manera:


constante crearUsuario = asíncrono (usuario) => {
constante nuevoUsuario = esperar userCollection.create (usuario);
consola.log("Usuario añadido a la base de datos");
consola.log (nuevoUsuario);
}

El siguiente código demuestra la función para crear un trabajo y agregarlo a la lista de trabajos de su cartel usando una transacción de base de datos.


constante creartrabajo = asíncrono (trabajo) => {
constante { correo electrónico de usuario, título, ubicación, salario } = trabajo;

// obtener el usuario de la base de datos
constante usuario = esperar colecciónUsuario.findOne({ correo electrónico: correo electrónico de usuario });

// iniciar sesión de transacción
constante sesión = esperar conexión.startSession();

// ejecutar todas las consultas de la base de datos en un bloque try-catch
intentar {
esperar sesión.startTransaction();

// crear trabajo
constante trabajo nuevo = esperar jobCollection.create(
[
{
título,
ubicación,
salario,
cartel: usuario._id,
},
],
{ sesión }
);
consola.log("Creado nuevo trabajo con éxito!");
consola.log (nuevoTrabajo[0]);

// agregar trabajo a la lista de usuarios de trabajos publicados
constante newJobId = newJob[0]._identificación;
constante añadido al usuario = esperar colecciónUsuario.findByIdAndUpdate(
usuario._id,
{ $addToSet: { trabajos: nuevoIdTrabajo } },
{ sesión }
);

consola.log("Trabajo agregado con éxito a la lista de trabajos del usuario");
consola.log (agregado al usuario);

esperar sesión.commitTransaction();

consola.log("Transacción DB realizada con éxito");
} atrapar (e) {
consola.error (e);
consola.log("Error al completar las operaciones de la base de datos");
esperar session.abortTransaction();
} finalmente {
esperar sesión.endSession();
consola.log("Sesión de transacción finalizada");
}
};

A crear La consulta que se ejecuta en una transacción generalmente toma y devuelve una matriz. Puedes ver esto en el código de arriba donde crea Nuevo trabajo y almacena su _identificación propiedad en elnuevoJobId variable.

Aquí hay una demostración de cómo funcionan las funciones anteriores:

constante usuariosimulado = {
nombre: "Timmy Omolana",
correo electrónico: "[email protected]",
};

constante trabajosimulado = {
título: "Gerente de Ventas",
ubicación: "Lagos, Nigeria",
salario: "$40,000",
correo electrónico de usuario: "[email protected]", // email del usuario creado
};

constante iniciarServidor = asíncrono () => {
esperar conectarDb();
esperar crear usuario (usuario simulado);
esperar crear trabajo (trabajo simulado);
};

iniciarServidor()
.entonces()
.catch((error) => consola.log (error));

Si guarda este código y lo ejecuta usando inicio de npm o el nodo comando, debería producir una salida como esta:

Otra forma de implementar transacciones ACID en MongoDB usando Mongoose es usando el conTransacción() función. Este enfoque proporciona poca flexibilidad ya que ejecuta todas las consultas dentro de una función de devolución de llamada que pasa como argumento a la función.

Podría refactorizar la transacción de base de datos anterior para usar conTransacción() como esto:

constante creartrabajo = asíncrono (trabajo) => {
constante { correo electrónico de usuario, título, ubicación, salario } = trabajo;

// obtener el usuario de la base de datos
constante usuario = esperar colecciónUsuario.findOne({ correo electrónico: correo electrónico de usuario });

// iniciar sesión de transacción
constante sesión = esperar conexión.startSession();

// ejecutar todas las consultas de la base de datos en un bloque try-catch
intentar {
constante éxito de la transacción = esperar session.withTransaction(asíncrono () => {
constante trabajo nuevo = esperar jobCollection.create(
[
{
título,
ubicación,
salario,
cartel: usuario._id,
},
],
{ sesión }
);

consola.log("Creado nuevo trabajo con éxito!");
consola.log (nuevoTrabajo[0]);

// agregar trabajo a la lista de usuarios de trabajos publicados
constante newJobId = newJob[0]._identificación;
constante añadido al usuario = esperar colecciónUsuario.findByIdAndUpdate(
usuario._id,
{ $addToSet: { trabajos: nuevoIdTrabajo } },
{ sesión }
);

consola.log("Trabajo agregado con éxito a la lista de trabajos del usuario");
consola.log (agregado al usuario);
});

si (transacción exitosa) {
consola.log("Transacción DB realizada con éxito");
} demás {
consola.log("Transacción fallida");
}
} atrapar (e) {
consola.error (e);
consola.log("Error al completar las operaciones de la base de datos");
} finalmente {
esperar sesión.endSession();
consola.log("Sesión de transacción finalizada");
}
};

Esto produciría el mismo resultado que la implementación anterior. Usted es libre de elegir qué estilo usar al implementar transacciones de base de datos en MongoDB.

Esta implementación no utiliza el cometerTransacción() y abortarTransacción() funciones Esto se debe a que el conTransacción() La función confirma automáticamente las transacciones exitosas y aborta las fallidas. La única función que debe llamar en todos los casos es la sesión.endSession() función.

Implementación de transacciones de base de datos ACID en MongoDB

Las transacciones de la base de datos son fáciles de usar cuando se realizan correctamente. Ahora debe comprender cómo funcionan las transacciones de la base de datos en MongoDB y cómo puede implementarlas en las aplicaciones de Node.js.

Para explorar más a fondo la idea de las transacciones ACID y cómo funcionan en MongoDB, considere crear una billetera fintech o una aplicación de blogs.