0
点赞
收藏
分享

微信扫一扫

MONGODB 谁说MONGODB 没有事务 2 细节与参数


MONGODB  谁说MONGODB 没有事务 2 细节与参数_stream

接上期,MongoDB 的事务操作已经操作了,但细节和参数并没有弄清楚,通过mongodb 的事务操作主要分为以下几个部分

1   Session.startTransaction 

2   Session.commitTransaction

3   Session.abortTransaction

简单的回顾一下,MONGODB 的事务,当一个事务中所有对数据的更改commit 后,外部是可以读取 commit 后的数据,在commit前这些数据在事务之外都不可见。事务中多个操作,其中之一失败,则事务整体失败,则在失败事务之前的操作全部丢弃。这里暂且认为MONGODB 的事务是  READ COMMITED 的方式对我们呈现的。

在昨天的示例里, mongodb 开始一个事务

session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );

需要注意的参数 readConcern  和  writeConcern 

readConcern 可以选择  snapshot  local  majority

这三者的不同点 snapshot 主要针对多文档的事务提交,在readConcern选择了snapshot后,保证了多文档提交后,读取数据是从大多数节点,保证数据的准确性,事务提交时 startTransaction 的readConcern 必须要选择 snapshot,  writeConcern 则也必须选择  marjority 保证写入的事务不会在回滚,确定在大多数节点已经落实。

对于事务的操作总,数据库中config, admin, local  collections 是无效的,system.开头的 collection 也是无效的,对于事务的操作仅仅限于客户自定义的collections。游标如果是在事务内发生的,则只能在事务内部调用,同理事务内部不能调用外部的游标。

在事务内也禁止使用 DDL 操作,如创建一个索引,一个collection  ,一个database ,创建账号 修改密码 等操作,事务内支持 CRUD 的操作。

事务的操作中,如果事务中的一个单独的操作失败了,是不会在进行重试,在事务commit 的阶段提交如果失败了,MONGODB 是会进行重试的。

那么一个完整的事务的提交并且包含重试和报错的程序怎么来操作

下面是一些操作步骤,

1  登陆mongoshell  通过mongosh 登陆 (不知道什么是mongosh 可以去官网看一下)

2   两个

function runTransactionWithRetry(txnFunc, session) {
    while (true) {
        try {
            txnFunc(session);  // performs transaction
            break;
        } catch (error) {
            if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError")  ) {
                print("TransientTransactionError, retrying transaction ...");
                continue;
            } else {
                throw error;
            }
        }
    }
}
function commitWithRetry(session) {
    while (true) {
        try {
            session.commitTransaction(); 
            print("Transaction committed.");
            break;
        } catch (error) {
            if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult") ) {
                print("UnknownTransactionCommitResult, retrying commit operation ...");
                continue;
            } else {
                print("Error during commit ...");
                throw error;
            }
       }
    }
}

事务函数

function updateEmployeeInfo(session) {
    employeesCollection = session.getDatabase("test").test;
    eventsCollection = session.getDatabase("test").test1;
    session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
    try{
        employeesCollection.insertOne( { employee: 3 }, { $set: { status: "Inactive" } } );
        eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
    } catch (error) {
        print("Caught exception during transaction, aborting.");
        session.abortTransaction();
        throw error;
    }
    commitWithRetry(session);
——————————————————————————————

执行MONGODB 事务

session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
try{
   runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
} finally {
   session.endSession();
}

执行后的结果。

具体MONGODB 在事务中可以操作的列表命令 在下方网址可以查询详细信息

Transactions and Operations — MongoDB Manual

MONGODB  谁说MONGODB 没有事务 2 细节与参数_java_02

后面还会关注MONGODB 的事务,以及一些案例。

MONGODB  谁说MONGODB 没有事务 2 细节与参数_java_03

举报

相关推荐

0 条评论