ITPub博客

首页 > 数据库 > 数据库开发技术 > MONGODB 谁说MONGODB 没有事务 2 细节与参数

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

原创 数据库开发技术 作者:liuaustin 时间:2022-02-23 00:00:00 0 删除 编辑

接上期,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 的事务,以及一些案例。



原文作者:AustinDatabases;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2018-11-13

  • 博文量
    1980
  • 访问量
    518171