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

2022-04-05 14:10:56 浏览数 (1)

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

0 人点赞