mongodb在4.0之前仅保证单个文档的操作是原子性的,对于多个文档,需要使用嵌套文档的方式进行处理。对于习惯了关系型数据库开发的同学来说,这显然很方不方便,所以在4.0之后, MongoDB开始在副本集
中提供multi-document
级别的事物支持,根据官网描述,multi-documen是指
- 单个集合中的多个文档
- 跨集合的文档
- 跨DB的文档
如果你目前还没有mongo集群,可以按照Mongo学习笔记(四) 创建副本集群replication set的方式快速搭建一个测试集群。
事物提交
@Test
public void testCommit() {
// Start a session.
ClientSession clientSession=mongoclient.startSession();
// Start Transaction.
clientSession.startTransaction();
MongoCollection<Foo> collection=mongoclient.getDatabase("test").getCollection("foo",Foo.class);
int i=0;
while (i<5){
Foo foo = new Foo();
foo.setX(2.0);
foo.setY(i);
i++;
//operation with session
collection.insertOne(clientSession,foo);
}
//commit
clientSession.commitTransaction();
clientSession.close();
}
事物回滚
@Test
public void testAbbot() {
ClientSession clientSession=mongoclient.startSession();
clientSession.startTransaction();
MongoCollection<Foo> collection=mongoclient.getDatabase("test").getCollection("foo",Foo.class);
int i=0;
while (i<5){
Foo foo = new Foo();
foo.setX(11.0);
foo.setY(i);
i++;
collection.insertOne(clientSession,foo);
}
clientSession.abortTransaction();
clientSession.close();
}
在使用事物前,需要首先开启一个session,然后通过startTransaction
方法开启事物,在进行数据交互时,需要将session作为参数传入,这样后续操作才会基于同一个事物,否则事物不生效,最后通过commitTransaction
提交事物。
Transactions 和Sessions的关系
所有的Transaction都依附于Session,对于同一个session,同一时刻仅能打开一个事务,如果会话结束,事务将全部回滚
使用限制
- 在使用事物时,所涉及的collection必须已经存在,不然会报错,以java客户端为例,会抛出如下异常
mongo-Cannot create namespace dbName.collectionName in multi-document transaction.
- 不可以对 config, admin, local 中的集合进行读/写操作
- 不可以写入system.* collections
- You cannot return the supported operation’s query plan (i.e. explain).
- For cursors created outside of transactions, you cannot call getMore inside a transaction.
- For cursors created in a transaction, you cannot call getMore outside the transaction.