A transaction is a series of database operations that will only succeed if all of the operations in the transaction are completed correctly. Transactions have long been a feature of relational databases, but they were mostly absent from document-oriented databases until recently.
In this article, you will learn about MongoDB Transactions on Single Node, their ACID properties, and how to use them in MongoDB.
The nature of Document-Oriented Databases, in which a single document can be a robust, nested structure containing embedded documents and arrays rather than only simple values, simplifies the storage of related data within a single document.
As a result, modifying multiple documents as part of a single logical operation is frequently unnecessary, which reduces the need for transactions in many applications.
Even with Document-Oriented Databases, some applications require accessing and modifying multiple documents in a single operation with guaranteed integrity. To meet the needs of such use cases, MongoDB Transactions on Single Nodes also have multi-document ACID transactions in version 4.0 of the database engine.
Table of Contents
Prerequisites
- One server with a regular, non-root user with sudo privileges and a UFW-enabled firewall.
- This tutorial was validated using an Ubuntu 20.04 server, and you can prepare your server by following this initial server setup tutorial for Ubuntu 20.04.
- MongoDB is installed on the server.
Introduction to MongoDB
Image Source
MongoDB is a well-known open-source NoSQL database built on C++. MongoDB is a Document-Oriented Database with a Dynamic Schema that stores data in JSON-like documents. It means that you don’t have to be concerned about the Data Structure, the number of fields or the types of fields used to store values when storing your records. Documents in MongoDB are similar to JSON objects.
By simply adding new fields or deleting existing ones, you can change the structure of records (referred to as Documents by MongoDB). This MongoDB feature simplifies the representation of Hierarchical Relationships, Store Arrays, and other more complexes Data Structures. MongoDB is now used by many tech behemoths, including Facebook, eBay, Adobe, and Google, to store massive amounts of data.
Key Features of MongoDB
Image Source
When compared to other traditional databases, MongoDB has a number of distinguishing features that make it a superior solution. Some of these characteristics are discussed in greater detail below:
- Fewer Schemas in a Database: A Schema-Less Database allows you to store different types of Documents in a single Collection (the equivalent of a table). In other words, a single collection in the MongoDB database can contain multiple Documents, each with its own set of Fields, Content, and Size. Because of this feature, MongoDB provides users with a great deal of flexibility.
- An Indexed Document: Every field in a MongoDB Database Document is indexed with Primary and Secondary Indices, which makes it easier to retrieve information from the data pool.
- Scalability: Sharding in MongoDB enables Horizontal Scalability. Sharding is the process of distributing data across multiple servers. A large amount of data is partitioned into data chunks using the Shard Key, and these data chunks are evenly distributed across Shards that span many Physical Servers.
- Replication: MongoDB ensures high data availability by replicating the data and sending it to multiple servers so that if one fails, the data can still be retrieved from another.
Hevo Data is a No-code Data Pipeline that offers a fully managed solution to set up Data Integration for 100+ Data Sources (including 40+ Free sources) and will let you directly load data from sources like MongoDB to a Data Warehouse or the Destination of your choice. It will automate your data flow in minutes without writing any line of code. Its fault-tolerant architecture makes sure that your data is secure and consistent. Hevo provides you with a truly efficient and fully automated solution to manage data in real-time and always have analysis-ready data.
Get Started with Hevo for Free
Let’s look at some of the salient features of Hevo:
- Fully Managed: It requires no management and maintenance as Hevo is a fully automated platform.
- Data Transformation: It provides a simple interface to perfect, modify, and enrich the data you want to transfer.
- Real-Time: Hevo offers real-time data migration. So, your data is always ready for analysis.
- Schema Management: Hevo can automatically detect the schema of the incoming data and map it to the destination schema.
- Connectors: Hevo supports 100+ Integrations to SaaS platforms FTP/SFTP, Files, Databases, BI tools, and Native REST API & Webhooks Connectors. It supports various destinations including Google BigQuery, Amazon Redshift, Snowflake, Firebolt, Data Warehouses; Amazon S3 Data Lakes; Databricks; MySQL, SQL Server, TokuDB, MongoDB, PostgreSQL Databases to name a few.
- Secure: Hevo has a fault-tolerant architecture that ensures that the data is handled in a secure, consistent manner with zero data loss.
- Hevo Is Built To Scale: As the number of sources and the volume of your data grows, Hevo scales horizontally, handling millions of records per minute with very little latency.
- Live Monitoring: Advanced monitoring gives you a one-stop view to watch all the activities that occur within Data Pipelines.
- Live Support: Hevo team is available round the clock to extend exceptional support to its customers through chat, email, and support calls.
Sign up here for a 14-Day Free Trial!
Recognizing ACID Transactions
Image Source
A transaction is a collection of database operations (such as reads and writes) that are performed in a sequential and all-or-nothing fashion. This means that in order for the results of these actions to be saved within the database and visible to other database clients outside of the transaction, all of the individual operations must succeed.
If any of the operations fails to complete correctly, the transaction is aborted, and any changes made since the start of the transaction are undone. The database will then be returned to its original condition as if the actions had never occurred.
The four database transaction properties that ensure such complex operations can be performed safely and reliably, ensuring data validity despite errors or interruptions, are abbreviated as an ACID: Atomicity, Consistency, Isolation, and Durability. If the database system can guarantee all four for a set of operations grouped into a transaction, it can also guarantee that the database will be left in a valid state even if unexpected errors in execution occur.
Atomicity
Atomicity refers to the fact that all of the actions in a transaction are treated as a single unit of work, and either all or none will be executed with nothing in between. The preceding example of money being debited from one account and added to another emphasizes the atomicity principle.
It is worth noting that in MongoDB, updates within a single document (regardless of how complex and nested the document structure is) are always atomic, even when no transactions are used. MongoDB Transactions on Single Nodes provide stronger atomicity guarantees only when there are multiple documents involved.
Consistency
Consistency refers to any changes made to a database that must adhere to the database’s existing constraints, or the entire transaction will fail. If one of the operations, for example, violated a unique index or a schema validation rule, MongoDB would abort the transaction.
Isolation
Isolation refers to the idea that separate, concurrently running transactions are isolated from one another and will not affect the outcomes of the other. The isolation rule guarantees that if two transactions are executed concurrently, the end result will be the same as if they were executed one after the other.
Durability
Durability ensures that as soon as the transaction is completed, the client can be confident that the data has been properly persisted. Even hardware failure or a power outage will not render the transaction null and void.
How MongoDB Transactions on Single Nodes are done
Here are 5 Easy to learn how MongoDB Transactions on Single Nodes can be done!
MongoDB Transactions on Single Nodes Step 1: Creating a Replica Set from a Standalone MongoDB Instance
MongoDB Transactions on Single Node can only be carried out on databases that are part of a larger cluster. This cluster can be a replica set or a sharded database cluster.
If you’ve already set up a replica set or sharded cluster to practice running transactions, you can skip this step and proceed to Step 2. If not, this step will walk you through the process of converting a standalone MongoDB instance into a single-node replica set.
Begin by opening the MongoDB configuration file in your preferred text editor to convert your standalone MongoDB instance into a replica set. This example
sudo nano /etc/mongod.conf
Rather than implementing more advanced security measures, it is best to disable the security block in your mongod.conf file for the purposes of this tutorial. To do so, use a pound sign to comment out every line in the security block:
. . .
#security:
# authorization: enabled
That is all the changes you need to make to this file in order to save and close it. If you used nano to edit the file, you can return to it by pressing CTRL + X, Y, and ENTER.
Then, restart the mongod service to apply the new configuration changes:
sudo systemctl restart mongod
Open the MongoDB shell after restarting the service to connect to the MongoDB instance running on your server:
mongo
Run the rs.initiate() method from the MongoDB prompt. This will convert your standalone MongoDB instance into a single-node replica set for testing:
rs.initiate()
If this method returns “ok”: 1 as an output, it means the replica set was successfully started:
If you run a command or simply press ENTER after a few moments, the prompt will update to reflect that you’re connected to the primary member of the replica set:
rs0: PRIMARY>
Your standalone MongoDB instance is now running as a single-node replica set, ready for transaction testing. Keep the prompt open for now, as you’ll use the MongoDB shell to create an example collection and insert some sample data into it in the next step.
MongoDB Transactions on Single Nodes Step 2: Getting Ready for the Sample Data
This step describes how to open the MongoDB shell and connect to the primary node of your replica set in order to explain how transactions in MongoDB work and how to use them. It also describes how to create a sample collection and add a few sample documents to it. This sample data will be used in this guide to demonstrate how to initiate and execute transactions.
If you skipped the preceding step because you already had a sharded MongoDB cluster or replica set, connect to any node that can write data:
$ mongo
To understand transaction behavior, you’ll need a set of documents to work with. This guide will make use of a collection of documents representing some of the world’s most populous cities. The following sample document, for example, represents Tokyo:
{
"name": "Tokyo",
"country": "Japan",
"continent": "Asia",
"population": 37.400
}
Run the insertMany() method to create a collection named cities and insert three documents into it at the same time:
db.cities.insertMany([
{"name": "Tokyo", "country": "Japan", "continent": "Asia", "population": 37.400 },
{"name": "Delhi", "country": "India", "continent": "Asia", "population": 28.514 },
{"name": "Seoul", "country": "South Korea", "continent": "Asia", "population": 25.674 }
])
The output will include a list of the object identifiers assigned to the newly added objects.
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("61646915c66c110cc07ca59b"),
ObjectId("61646915c66c110cc07ca59c"),
ObjectId("61646915c66c110cc07ca59d")
]
}
Finally, use the createIndex() method to create an index that ensures each document in the collection has a unique value for the name field. This will be useful for testing consistency requirements later in this guide when running transactions:
db.cities.createIndex( { "name": 1 }, { "unique": true } )
MongoDB will confirm that the index was successfully created:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"commitQuorum" : "votingMembers",
"ok" : 1,
. . .
}
MongoDB Transactions on Single Nodes Step 3: Creating Your First Successful Transaction
This step describes how to create a transaction that consists of a single operation that inserts a new document into the previous step’s sample collection.
Begin by launching two MongoDB shell sessions. One will be used to execute transaction commands, while the other will allow you to see what data is available to other database users outside the transaction at various points in time.
If you query the cities collection at this point, both shell sessions should list the three cities you inserted previously. Verify this by running the following find() query in both shell sessions, beginning with the first:
db.cities.find()
{ "_id" : ObjectId("61646915c66c110cc07ca59b"), "name" : "Tokyo", "country" : "Japan", "continent" : "Asia", "population" : 37.4 }
{ "_id" : ObjectId("61646915c66c110cc07ca59c"), "name" : "Delhi", "country" : "India", "continent" : "Asia", "population" : 28.514 }
{ "_id" : ObjectId("61646915c66c110cc07ca59d"), "name" : "Seoul", "country" : "South Korea", "continent" : "Asia", "population" : 25.674 }
After confirming that the output of this query is consistent across both sessions, attempt to insert a new document into the collection. You will, however, insert this document as part of a transaction rather than using the insertOne() method.
Transactions aren’t typically written and executed from the MongoDB Shell, as this guide explains. Transactions are more often than not used by external applications. The application must start a session to ensure that any transactions it performs are Atomic, Consistent, Isolated, and Durable.
MongoDB Transactions on Single Nodes Step 4: Abandoning a Transaction
This step is similar to the previous one in that it requires you to initiate a transaction in the same manner. This step, on the other hand, describes how to cancel the transaction rather than commit the changes. When this is done, all changes introduced by the transaction are undone, restoring the database to its previous state as if the transaction had never occurred.
Following the preceding step, you will have four cities in your collection, including the newly added one representing New York.
Start the session in the first MongoDB shell and assign it to the session variable again:
var session = db.getMongo().startSession()
Assume you made a mistake and no longer wish to complete the transaction. Instead, you want to cancel any statements you’ve run as part of this session and end the transaction. To accomplish this, use the abortTransaction() method:
session.abortTransaction()
The abortTransaction() method instructs MongoDB to discard all changes made during the transaction and return the database to its previous state. This command, like startTransaction and commitTransaction, produces no output if it succeeds.
List the documents from the cities collection in both MongoDB shells after successfully aborting the transaction. First, in the running session, perform the following operation:
cities.find()
Aborting the transaction after the document has been inserted but before the transaction has been committed is the same as if the document was never inserted.
You learned how to terminate a transaction and undo the changes made during its lifetime in this step. However, transactions are not always manually aborted in this manner. MongoDB will frequently terminate a transaction before it can be executed because one of the operations within the transaction caused an error.
MongoDB Transactions on Single Nodes Step 5: Transactions Aborted Due to Errors
This step is similar to the one before it, but this time you’ll learn what happens if an error occurs during any of the statements executed within the transaction.
You should still have two shell sessions open at this point. Your collection contains four cities, one of which is a newly added document representing New York. The document representing Buenos Aires, on the other hand, was not inserted because it was discarded when you aborted the transaction in the previous step.
Begin the session in the first MongoDB shell and assign it to the session variable:
var session = db.getMongo().startSession()
Recreate the cities variable:
var cities = session.getDatabase('test').getCollection('cities')
Then, as part of the ongoing transaction, insert another new document into this collection. In this example, a document representing Osaka, Japan is inserted
cities.insertOne({"name": "Osaka", "country": "Japan", "continent": "Asia", "population": 19.281 })
From within the transaction, the newly inserted city will be immediately visible
{ "_id" : ObjectId("61646915c66c110cc07ca59b"), "name" : "Tokyo", "country" : "Japan", "continent" : "Asia", "population" : 37.4 }
{ "_id" : ObjectId("61646915c66c110cc07ca59c"), "name" : "Delhi", "country" : "India", "continent" : "Asia", "population" : 28.514 }
{ "_id" : ObjectId("61646915c66c110cc07ca59d"), "name" : "Seoul", "country" : "South Korea", "continent" : "Asia", "population" : 25.674 }
{ "_id" : ObjectId("6164849d53abeea9d9dd10cf"), "name" : "New York", "country" : "United States", "continent" : "North America", "population" : 18.819 }
As part of this transaction, perform the following operation to try to insert one more document into the collection. This command will generate a new document that represents New York City.
MongoDB will return an error message indicating that the unique constraint was violated
Output
WriteError({
"index" : 0,
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.cities index: name_1 dup key: { name: "New York" }",
"op" : {
"_id" : ObjectId("61648bdc322518cf706858b7"),
"name" : "New York",
"country" : "United States",
"continent" : "North America",
"population" : 18.819
}
})
When an error occurs within a transaction, MongoDB will automatically abort the transaction. Furthermore, because transactions are executed all-or-nothing, no changes made within the transaction are persisted in this case. MongoDB aborted the transaction and discarded the document representing Osaka due to the error caused by adding a second document representing New York.
Conclusion
You became acquainted with ACID principles and multi-document transactions in MongoDB by reading this article. You started a transaction, inserted documents as part of it, and discovered when the document becomes visible inside and outside the transaction. You learned how to commit a transaction, how to abort it and roll back any changes, and what happens if an error occurs within the transaction.
The tutorial only gave a cursory overview of MongoDB Transactions on Single Nodes. We recommend that you read the official MongoDB documentation to learn more about how transactions work.
To meet the growing storage and computing needs of data, you will need to invest some of your engineering bandwidth in integrating data from all sources, cleaning and transforming it, and finally loading it into a Cloud Data Warehouse for further Business Analytics. A Cloud-Based ETL tool, such as Hevo Data, can efficiently handle all of these challenges.
Visit our Website to Explore Hevo
Hevo Data, a No-code Data Pipeline provides you with a consistent and reliable solution to manage data transfer between a variety of sources like MongoDB and a wide variety of Desired Destinations, with a few clicks. Hevo Data with its strong integration with 100+ sources (including 40+ free sources) allows you to not only export data from your desired data sources & load it to the destination of your choice, but also transform & enrich your data to make it analysis-ready so that you can focus on your key business needs and perform insightful analysis using BI tools.
Want to take Hevo for a spin? Sign Up for a 14-day free trial and experience the feature-rich Hevo suite first hand. You can also have a look at the unbeatable pricing that will help you choose the right plan for your business needs.
Share with us your experience of MongoDB Transactions on Single Nodes in the comments below!
Davor is a data analyst at heart with a passion for data, software architecture, and writing technical content. He has experience writing more than 100 articles on data integration and infrastructure.