Questions
What are transactions and how do you use them in MongoDB?
The Scenario
You are a backend engineer at a fintech company. You are writing a new service that needs to transfer money from one account to another.
The transfer consists of two separate operations: a updateOne to the sender’s account to debit the money, and a updateOne to the receiver’s account to credit the money.
You need to make sure that both operations are executed successfully, or that neither of them are.
The Challenge
Explain what transactions are in MongoDB and how you would use them to solve this problem. What are the key properties of a transaction (ACID)?
A junior engineer might try to solve this problem by just executing the two `updateOne` statements one after the other. This would be a very risky solution, because if the second `updateOne` statement fails, the money will be debited from the sender's account but not credited to the receiver's account.
A senior engineer would know that a transaction is the perfect tool for this job. They would be able to explain what a transaction is and how to use it to make sure that both `updateOne` statements are executed successfully, or that neither of them are.
Step 1: Understand What Transactions Are
A transaction is a sequence of one or more operations that are executed as a single logical unit.
Step 2: The ACID Properties
MongoDB transactions are ACID compliant.
| Property | Description |
|---|---|
| Atomicity | All the operations in a transaction are executed successfully, or none of them are. |
| Consistency | A transaction brings the database from one valid state to another. |
| Isolation | The intermediate state of a transaction is not visible to other transactions. |
| Durability | Once a transaction has been committed, it will remain committed even in the event of a power failure. |
Step 3: Use a Transaction
Here’s how we can use a transaction to transfer money from one account to another:
const session = db.getMongo().startSession();
session.startTransaction();
try {
session.getDatabase("mydb").getCollection("accounts").updateOne(
{ _id: 1 },
{ $inc: { balance: -100 } }
);
session.getDatabase("mydb").getCollection("accounts").updateOne(
{ _id: 2 },
{ $inc: { balance: 100 } }
);
} catch (error) {
session.abortTransaction();
throw error;
}
session.commitTransaction();
session.endSession();In this example, we start a new session and a new transaction. We then execute the two updateOne statements. If both statements are successful, we commit the transaction. If either statement fails, we abort the transaction.
Practice Question
You are in the middle of a transaction and you want to undo all the changes that you have made so far. Which of the following would you use?