MongoDB transactions?
Playing around with MongoDB and NoRM in .NET.
Thing开发者_开发百科 that confused me - there are no transactions
(can't just tellMongoConnection.Begin/EndTransaction
or something like that).
I want to use Unit of work pattern and rollback changes in case something fails.
Is there still a clean way how to enrich my repository with ITransaction?
MongoDB doesn't support complex multi-document transactions. If that is something you absolutely need it probably isn't a great fit for you.
In most cases, however, we've found that complex transactions aren't a requirement. All operations in MongoDB are atomic on a single document, and we support nice update modifiers, which make a lot of operations that would need a transaction easy to implement (and fast).
That is true that MongoDB does't support transaction out of the box, but you can implement optimistic transactions on your own. They fit fine the unit of work. I wrote an java example and some explanation on a GitHub so you can easily repeat in C#.
As of v4.0, MongoDB supports multi-document ACID transactions. Through snapshot isolation, transactions provide a globally consistent view of data, and enforce all-or-nothing execution to maintain data integrity. For more info, see https://www.mongodb.com/transactions
In 4.2, MongoDB will also support sharded transactions.
In this blog post, I also outline our journey to multi-document ACID transactions, in case if you are interested in the history and our reasoning.
MongoDB 4.0 will add support for multi-document transactions.
https://www.mongodb.com/transactions
Some notes for the record.
While MongoDB does not have transaction support, it supports atomicity on a single document:
MongoDB does have support for atomic operations within a single document. Given the possibilities provided by nested documents, this feature provides support for a large number of use-cases.
Also, the manual entry about "Isolate Sequence of Operations" might be interesting. E.g.:
however, you can isolate a single write operation that affects multiple documents using the isolation operator.
You can use instead MongoDb TokuMX.
http://www.tokutek.com/products/tokumx-for-mongodb/
TokuMXTM is an open source, high-performance distribution of MongoDB that has dramatically improved performance and operational efficiency compared to basic MongoDB. TokuMX is a drop-in replacement for MongoDB, and offers 20X performance improvements, 90% reduction in database size, and support for ACID transactions with MVCC.
FYI - this has now changed
using (var session = mongoDbContext.MongoDatabase.Client.StartSession())
{
var itemAuthRepo = (Repository<ItemAuthorization, ObjectId>)mongoDbContext.ItemAuthorizations;
var calendarRepo = (Repository<CalendarEvent, ObjectId>)mongoDbContext.Calendars;
if (itemAuthRepo != null && calendarRepo!=null)
{
session.StartTransaction();
try
{
itemAuthRepo.Collection.InsertOne(session, newItemAuthorization);
calendarRepo.Collection.InsertOne(session, cal);
session.CommitTransaction();
}
catch (Exception ex)
{
session.AbortTransaction();
throw;
}
}
else
{
throw new Exception("IRepository was not casted to Repository");
}
}
Yes, there are multiple ways to apply Unit of Work pattern for MongoDB depending on the database version.
Until MongoDB 4.0, there was no support for multi-document ACID transactions. Then developers has used "two-phase commit protocol" (single database) and "three-phase commit protocol" (non-blocking on distributed databases) to create their own transaction layer which has provided data consistency but not all-or-nothing execution to maintain data integrity. So that way has taken down the performance.
MongoDB 4.0 has added support for multi-document ACID transactions.
Sources:
https://en.wikipedia.org/wiki/Two-phase_commit_protocol
https://en.wikipedia.org/wiki/Three-phase_commit_protocol
https://www.mongodb.com/transactions
MongoDB supports transaction from version 4.0 onwards and from version 4.4 it also supports creating collections in transaction
I just enabled and tested transaction in mongoDB using free cluster provided by mongoDB atlas which uses mongoDB version 5.0
Following settings should work for mongoDB version 4.2+, although not tested yet.
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<properties>
<java.version>11</java.version>
<mongodb.version>4.4.0</mongodb.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.7.0</version>
</dependency>
MongoConfig.java
@Configuration
public class MongoConfig
{
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory
mongoDatabaseFactory)
{
return new MongoTransactionManager(mongoDatabaseFactory);
}
}
then add @Transactional on function where you want to enable transaction.
It worked for me !
精彩评论