Transactions in MongoDB are operations that allow you to execute multiple operations as a single unit of work. They ensure that all operations either succeed together or fail together, maintaining data consistency across your database.
ACID Properties in MongoDB Transactions
All operations in a transaction are treated as a single unit. Either all operations succeed, or none of them do.
// Example of atomic transaction
const session = client.startSession();
try {
session.startTransaction();
// Perform multiple operations
await accounts.updateOne(
{ _id: "account1" },
{ $inc: { balance: -100 } },
{ session }
);
await accounts.updateOne(
{ _id: "account2" },
{ $inc: { balance: 100 } },
{ session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
Transactions maintain database consistency by ensuring that all data remains in a valid state.
// Example of maintaining consistency
const session = client.startSession();
try {
session.startTransaction();
// Check balance before transfer
const account = await accounts.findOne(
{ _id: "account1" },
{ session }
);
if (account.balance < 100) {
throw new Error("Insufficient funds");
}
// Perform transfer
await accounts.updateOne(
{ _id: "account1" },
{ $inc: { balance: -100 } },
{ session }
);
await accounts.updateOne(
{ _id: "account2" },
{ $inc: { balance: 100 } },
{ session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
Transactions are isolated from each other, preventing concurrent transactions from interfering with each other.
// Example of transaction isolation
const session = client.startSession();
try {
session.startTransaction();
// Read with transaction isolation
const result = await orders.findOne(
{ _id: "order1" },
{ session }
);
// Update with transaction isolation
await orders.updateOne(
{ _id: "order1" },
{ $set: { status: "processing" } },
{ session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
Once a transaction is committed, its changes are permanent and survive system failures.
// Example of durable transaction
const session = client.startSession();
try {
session.startTransaction();
// Perform critical operations
await orders.insertOne({
_id: "order1",
items: ["item1", "item2"],
total: 200
}, { session });
await inventory.updateMany(
{ _id: { $in: ["item1", "item2"] } },
{ $inc: { quantity: -1 } },
{ session }
);
// Commit ensures durability
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
// Start a new session
const session = client.startSession();
// Start a transaction
session.startTransaction();
// Commit the transaction
await session.commitTransaction();
// End the session
session.endSession();
// Abort the transaction
await session.abortTransaction();
// End the session
session.endSession();
Now that you understand transactions, you can explore: