0% completed
Transactions in MongoDB allow multiple operations to be executed in a single atomic unit of work. This ensures that all operations within a transaction either complete successfully or none of them do, maintaining data consistency.
MongoDB transactions are designed to follow the ACID properties:
Atomicity ensures that all the operations within a transaction are completed successfully. If any operation fails, the entire transaction fails, and the database state is left unchanged. This property is crucial for maintaining consistency, especially in scenarios involving multiple related operations.
Example: Imagine transferring $50 from Alice's account to Bob's account. Both operations (debiting Alice's account and crediting Bob's account) must succeed or fail together.
Consistency ensures that a transaction brings the database from one valid state to another, maintaining the integrity of the database. This means that any data written to the database must be valid according to all defined rules, including constraints, cascades, and triggers.
Example: In our example, the balance of Alice's and Bob's accounts should remain consistent before and after the transaction. If Alice's balance is debited and Bob's balance is credited correctly, the database remains consistent.
Isolation ensures that the operations within a transaction are isolated from other operations. This means that intermediate states of a transaction are not visible to other operations, ensuring that concurrent transactions do not interfere with each other.
Example: If another transaction tries to read the balance of Alice or Bob while our transaction is in progress, it will not see the intermediate state where only one account is updated.
Durability ensures that once a transaction has been committed, it will remain so, even in the event of a system failure. This guarantees that the changes made by the transaction are permanently applied to the database.
Example: Once the transaction for transferring $50 from Alice to Bob is committed, the changes are permanent and will persist even if the system crashes immediately afterward.
Execute the below query to add data to the MongoDB database.
db.users.insertMany([ { _id: 1, name: "Alice", balance: 100 }, { _id: 2, name: "Bob", balance: 200 } ]) db.accounts.insertMany([ { _id: 1, userId: 1, accountType: "savings", balance: 100 }, { _id: 2, userId: 2, accountType: "checking", balance: 200 } ])
Let's create a Node.js script to demonstrate a transaction. You can refer to the MongoDB With NodeJS
chapter to get in-depth guide about setting up MongoDB environment with NodeJS.
The script will transfer $50 from Alice's account to Bob's account.
First, ensure you have Node.js installed. Initialize a new project and install the MongoDB driver:
npm init -y npm install mongodb
Create a file named transaction.js
and add the following code:
const { MongoClient } = require("mongodb"); async function run() { // Connection URI const uri = "mongodb://localhost:27017"; // Create a new MongoClient const client = new MongoClient(uri); try { // Connect to the MongoDB cluster await client.connect(); // Specify the database and collections const database = client.db("bank"); const users = database.collection("users"); const accounts = database.collection("accounts"); // Start a session const session = client.startSession(); // Start a transaction session.startTransaction(); try { // Update Alice's balance by subtracting $50 const aliceUpdate = await users.updateOne( { _id: 1 }, { $inc: { balance: -50 } }, { session } ); // Check if Alice's document was found and updated if (aliceUpdate.matchedCount === 0) { throw new Error("Alice's document not found"); } // Update Bob's balance by adding $50 const bobUpdate = await users.updateOne( { _id: 2 }, { $inc: { balance: 50 } }, { session } ); // Check if Bob's document was found and updated if (bobUpdate.matchedCount === 0) { throw new Error("Bob's document not found"); } // Commit the transaction await session.commitTransaction(); console.log("Transaction committed."); } catch (error) { // If any error occurred, abort the transaction console.log("Transaction aborted. Error:", error); await session.abortTransaction(); } finally { // End the session session.endSession(); } } finally { // Close the client connection await client.close(); } } run().catch(console.dir);
MongoClient
.const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri); await client.connect();
client.startSession()
, which is necessary for managing the transaction.const session = client.startSession();
session.startTransaction()
.session.startTransaction();
const aliceUpdate = await users.updateOne( { _id: 1 }, { $inc: { balance: -50 } }, { session } ); if (aliceUpdate.matchedCount === 0) { throw new Error("Alice's document not found"); } const bobUpdate = await users.updateOne( { _id: 2 }, { $inc: { balance: 50 } }, { session } ); if (bobUpdate.matchedCount === 0) { throw new Error("Bob's document not found"); }
session.commitTransaction()
.await session.commitTransaction();
session.abortTransaction()
, ensuring that no partial changes are applied.catch (error) { console.log("Transaction aborted. Error:", error); await session.abortTransaction(); }
session.endSession()
, and the client connection is closed to free up resources.finally { session.endSession(); await client.close(); }
Transactions in MongoDB provide a robust mechanism for ensuring data consistency and integrity across multiple operations. By following the ACID properties, MongoDB transactions ensure that all operations within a transaction are completed successfully or not at all. This lesson covered the basics of transactions, their syntax, practical examples, use cases, and considerations, providing a comprehensive understanding of how to implement and use transactions in MongoDB effectively.
.....
.....
.....