Wednesday, 16 June 2021

MongoDB: Transaction support

In database world, a transaction represents a single unit of work and represents the change in a database.

 

A database transaction must satisfy following properties.

a.   Atomicity: Transaction must either be complete in its entirety or have no effect whatsoever

b.   Consistency: Transaction must conform to existing constraints in the database

c.    Isolation: Transaction must not affect other transactions

d.   Durability: Changes to the database get written to persistent storage.

 

MongoDB maintains atomicity at document level by default. That means, when you are writing a document to mongoDB, it writes it completely else nothing will be written.

 

But if you are working with multiple documents, and multiple collections, you need to use transactions to achieve this atomicity.

 

For example, let’s model an author and book relationship.

 

Define authors collection

db.authors.insertMany([
	{
		"firstName": "Rama Krishna",
		"lastName" : "Gurram"
	},
	{
		"firstName" : "Sailaja",
		"lastName" : "Ptr"
	}
])

> db.authors.insertMany([
... {
... "firstName": "Rama Krishna",
... "lastName" : "Gurram"
... },
... {
... "firstName" : "Sailaja",
... "lastName" : "Ptr"
... }
... ])
{
	"acknowledged" : true,
	"insertedIds" : [
		ObjectId("60cae3c0fc455868b4f32103"),
		ObjectId("60cae3c0fc455868b4f32104")
	]
}
> 
>
>
> db.authors.find().pretty()
{
	"_id" : ObjectId("60cae3c0fc455868b4f32103"),
	"firstName" : "Rama Krishna",
	"lastName" : "Gurram"
}
{
	"_id" : ObjectId("60cae3c0fc455868b4f32104"),
	"firstName" : "Sailaja",
	"lastName" : "Ptr"
}

 

Let’s define books collection

db.books.insertMany([
	{
		"bookName": "Programming Puzzles",
		"price": "450",
		"noOfPage": 345,
		"authorId" : ObjectId("60cae3c0fc455868b4f32103")
	},
	{
		"bookName": "Mastering Java puzzles",
		"price": "650",
		"noOfPage": 900,
		"authorId" : ObjectId("60cae3c0fc455868b4f32103")
	},
	{
		"bookName": "Explore nNature",
		"price": "150",
		"noOfPage": 1200,
		"authorId" : ObjectId("60cae3c0fc455868b4f32104")
	}
])

 

> db.books.find().pretty()
{
	"_id" : ObjectId("60cae467fc455868b4f32105"),
	"bookName" : "Programming Puzzles",
	"price" : "450",
	"noOfPage" : 345,
	"authorId" : ObjectId("60cae3c0fc455868b4f32103")
}
{
	"_id" : ObjectId("60cae467fc455868b4f32106"),
	"bookName" : "Mastering Java puzzles",
	"price" : "650",
	"noOfPage" : 900,
	"authorId" : ObjectId("60cae3c0fc455868b4f32103")
}
{
	"_id" : ObjectId("60cae467fc455868b4f32107"),
	"bookName" : "Explore nNature",
	"price" : "150",
	"noOfPage" : 1200,
	"authorId" : ObjectId("60cae3c0fc455868b4f32104")
}

 

I want to delete the author "Rama Krishna" and all the books that he written from the database. Since this use case deals with two collections, we should go for a transaction support. If you try without transaction support, you may get data inconsistency. For example, author information may be deleted, and books are not deleted due to some hardware or business logic issue.

 

Basic steps in the transaction

There are three basic steps in the transaction flow.

a.   Begin the transaction.

b.   Execute a set of queries

c.    If no error occurs, then commit the transaction. If an error occurs, then roll back the transaction.

 

Follow below step-by-step procedure to delete the author and book documents.

 

Step 1: Start the session.

const session = db.getMongo().startSession()

 

Step 2: Start the transaction.

session.startTransaction()

Step 3: Get collection instances.

const authorsCollection = session.getDatabase("sample").authors
const booksauthorsCollection = session.getDatabase("sample").books


Step 4: Perform the operations.

authorsCollection.deleteOne({"_id" : ObjectId("60cae3c0fc455868b4f32103")})
booksauthorsCollection.deleteMany({"authorId" : ObjectId("60cae3c0fc455868b4f32103")})


Step 5: Commit the transaction.

session.commitTransaction()


Note

a. If you do not want to continue, you can abort the transaction.

session.abortTransaction()

 

b. If you try to start a session on a standalone server, you'll get this error.

Transaction numbers are only allowed on a replica set member or mongos

 

In order to use transactions, you need a MongoDB replica set

 

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment