【MongoDB】4.0版本事务上手测试
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,事务上手测试基础:原来3版本的只能叫单文档事务,即针对行的事务。所以没必要显式提供调用,多文档事务由于有损耗,照顾到性能的需求,提供了事务开启关闭的接口。多行,多集合,多库之间读肯定会牵扯到一致性读,
千家信息网最后更新 2026年11月02日【MongoDB】4.0版本事务上手测试
事务上手测试
基础:
原来3版本的只能叫单文档事务,即针对行的事务。所以没必要显式提供调用,多文档事务由于有损耗,照顾到性能的需求,提供了事务开启关闭的接口。
多行,多集合,多库之间读肯定会牵扯到一致性读,所以多文档事务肯定是有必要的。
4.2版本可能会支持分片系统多文档事务,4.0的多文档事务最多只面向复制集
准备
集合:
use dba;[10.240.129.36:30001_primary@dba]> db.coll_2.find()[10.240.129.36:30001_primary@dba]> db.coll_1.find(){ "_id" : ObjectId("5b371e120d6160b73a9fcee6"), "test" : true }{ "_id" : ObjectId("5b371e6d0d6160b73a9fcee7"), "test" : true }精简命令:
mysql">// 显式开启一个会话(难道通过shell链接来本身不就是会话吗?)session=db.getMongo().startSession()// 显式开启事务session.startTransaction()// 获取表对象coll_1=session.getDatabase('dba').coll_1coll_2=session.getDatabase('dba').coll_2;// 使用表对象的插入函数进行插入coll_1.insertOne({'not_test':false})coll_2.insertOne({'not_test':false})// 提交事务session.commitTransaction()// 回滚事务session.abortTransaction()// 检查事务准确性db.coll_1.find()db.coll_2.find()超时参数怎么设置?
默认事务生命周期为60秒,超出后会被自动清理
// The minimum value for transactionLifetimeLimitSeconds is 1 second.db.adminCommand( { setParameter: 1, transactionLifetimeLimitSeconds: 30 } )// You can also set parameter transactionLifetimeLimitSeconds at startup time.// 可以考虑写在配置文件中mongod --setParameter "transactionLifetimeLimitSeconds=30"第一次尝试
因为忘记设置后向兼容性,执行失败,在同一个shell中进行设置后,再次插入,提示事务不存在
[10.240.129.36:30001_primary@dba]> Session.startTransactions()2018-06-30T14:17:10.670+0800 E QUERY [js] ReferenceError: Session is not defined :@(shell):1:1[10.240.129.36:30001_primary@dba]> db.getMongo()connection to 127.0.0.1:30001[10.240.129.36:30001_primary@dba]> db.getMongo().startSession()session { "id" : UUID("887f4564-4f8a-4783-886d-a55a536f41aa") }[10.240.129.36:30001_primary@dba]> session=db.getMongo().startSession()session { "id" : UUID("9b3e10b9-93cd-4010-b1a3-0e7b49796db3") }[10.240.129.36:30001_primary@dba]> session.startTransaction()[10.240.129.36:30001_primary@dba]> coll_1=session.getDatabase('dba').coll_1;dba.coll_1[10.240.129.36:30001_primary@dba]> coll_2=session.getDatabase('dba').coll_2;dba.coll_2[10.240.129.36:30001_primary@dba]> coll_1.insertOne({'not_test':false})// 后向兼容性要求为4,也就是说想开启事务必须是mongod4以上的版本2018-06-30T14:28:55.708+0800 E QUERY [js] WriteCommandError: Transactions are only supported in featureCompatibilityVersion 4.0. See http://dochub.mongodb.org/core/4.0-feature-compatibility for more information. :WriteCommandError({ "ok" : 0, "errmsg" : "Transactions are only supported in featureCompatibilityVersion 4.0. See http://dochub.mongodb.org/core/4.0-feature-compatibility for more information.", "code" : 50773, "codeName" : "Location50773"})WriteCommandError@src/mongo/shell/bulk_api.js:420:48Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:252:9@(shell):1:1[10.240.129.36:30001_primary@dba]> db.adminCommand({setFeatureCompatibilityVersion:'4.0'}){ "ok" : 1 }// 可以看到,报错,重新设置版本兼容性后,原先的事务出现了问题[10.240.129.36:30001_primary@dba]> coll_1.insertOne({'not_test':false})2018-06-30T14:31:16.706+0800 E QUERY [js] WriteCommandError: Given transaction number 0 does not match any in-progress transactions. :WriteCommandError({ "errorLabels" : [ "TransientTransactionError" ], "ok" : 0, "errmsg" : "Given transaction number 0 does not match any in-progress transactions.", "code" : 251, "codeName" : "NoSuchTransaction"})WriteCommandError@src/mongo/shell/bulk_api.js:420:48Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:252:9@(shell):1:1// 事务怎么也调不好了[10.240.129.36:30001_primary@dba]> session.startTransaction()2018-06-30T14:33:53.293+0800 E QUERY [js] Error: Transaction already in progress on this session. :startTransaction@src/mongo/shell/session.js:732:1startTransaction@src/mongo/shell/session.js:925:17@(shell):1:1[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]>[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]> db.getMongo().abortTransaction[10.240.129.36:30001_primary@dba]> exit// 直接退出当前连接第二次尝试:
[10.240.129.36:30001_primary@admin]> session=db.getMongo().startSession()session { "id" : UUID("b82d71b0-b698-4909-b5b8-a7845dba98b2") }[10.240.129.36:30001_primary@admin]> session.startTransaction()[10.240.129.36:30001_primary@admin]> coll_1=session.getDatabase('dba').coll_1dba.coll_1[10.240.129.36:30001_primary@admin]> coll_2=session.getDatabase('dba').coll_2;dba.coll_2[10.240.129.36:30001_primary@admin]> coll_1.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b37270429c5c0c486b4b17b")}[10.240.129.36:30001_primary@admin]> coll_2.insertOne({'not_test':false})// 这里的事务回滚可能是因为超时引起的,默认事务生命周期最大值为1分钟2018-06-30T15:00:50.629+0800 E QUERY [js] WriteCommandError: Transaction 0 has been aborted. :WriteCommandError({ "errorLabels" : [ "TransientTransactionError" ], "ok" : 0, "errmsg" : "Transaction 0 has been aborted.", "code" : 251, "codeName" : "NoSuchTransaction"})WriteCommandError@src/mongo/shell/bulk_api.js:420:48Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:252:9@(shell):1:1[10.240.129.36:30001_primary@admin]> coll_2.insertOne({'not_test':false})2018-06-30T15:00:59.308+0800 E QUERY [js] WriteCommandError: Transaction 0 has been aborted. :WriteCommandError({ "errorLabels" : [ "TransientTransactionError" ], "ok" : 0, "errmsg" : "Transaction 0 has been aborted.", "code" : 251, "codeName" : "NoSuchTransaction"})WriteCommandError@src/mongo/shell/bulk_api.js:420:48Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21DBCollection.prototype.insertOne@src/mongo/shell/crud_api.js:252:9@(shell):1:1// 事务超时回滚之后,应该还可以重开新的事务才对,这里老是报错[10.240.129.36:30001_primary@admin]> session.startTransaction()2018-06-30T15:01:04.932+0800 E QUERY [js] Error: Transaction already in progress on this session. :startTransaction@src/mongo/shell/session.js:732:1startTransaction@src/mongo/shell/session.js:925:17@(shell):1:1// 内部已经回滚掉了,结果竟然需要我手动回滚才行,晕[10.240.129.36:30001_primary@admin]> session.abortTransaction()[10.240.129.36:30001_primary@admin]> session.startTransaction()[10.240.129.36:30001_primary@admin]> coll_1.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b372ac229c5c0c486b4b17e")}[10.240.129.36:30001_primary@admin]> coll_2.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b372ac529c5c0c486b4b17f")}// 试试能不能进行explain操作[10.240.129.36:30001_primary@admin]> coll_1.explain().find({'test_explain':1})2018-06-30T15:03:09.375+0800 E QUERY [js] Error: explain failed: { "ok" : 0, "errmsg" : "Cannot run 'explain' in a multi-document transaction.", "code" : 50767, "codeName" : "Location50767"} : // 果然是报错了呢,在事务中不能进行explain操作_getErrorWithCode@src/mongo/shell/utils.js:25:13throwOrReturn@src/mongo/shell/explainable.js:31:1constructor/this.finish@src/mongo/shell/explain_query.js:171:24constructor/this.shellPrint@src/mongo/shell/explain_query.js:210:26shellPrintHelper@src/mongo/shell/utils.js:594:1@(shell2):1:1// 尝试提交时报错[10.240.129.36:30001_primary@admin]> session.commitTransaction()2018-06-30T15:04:21.985+0800 E QUERY [js] Error: command failed: { "errorLabels" : [ "TransientTransactionError" ], "ok" : 0, "errmsg" : "Transaction 1 has been aborted.", "code" : 251, "codeName" : "NoSuchTransaction"} :_getErrorWithCode@src/mongo/shell/utils.js:25:13doassert@src/mongo/shell/assert.js:18:14_assertCommandWorked@src/mongo/shell/assert.js:534:17assert.commandWorked@src/mongo/shell/assert.js:618:16commitTransaction@src/mongo/shell/session.js:929:17@(shell):1:1[10.240.129.36:30001_primary@dba]> db.coll_1.find(){ "_id" : ObjectId("5b371e120d6160b73a9fcee6"), "test" : true }{ "_id" : ObjectId("5b371e6d0d6160b73a9fcee7"), "test" : true }[10.240.129.36:30001_primary@dba]> db.coll_2.find()// 这边可以看到,插入语句并没有真正被执行[10.240.129.36:30001_primary@dba]> session.commitTransaction()2018-06-30T15:05:46.288+0800 E QUERY [js] Error: command failed: { "errorLabels" : [ "TransientTransactionError" ], "ok" : 0, "errmsg" : "Transaction 1 has been aborted.", "code" : 251, "codeName" : "NoSuchTransaction"} :_getErrorWithCode@src/mongo/shell/utils.js:25:13doassert@src/mongo/shell/assert.js:18:14_assertCommandWorked@src/mongo/shell/assert.js:534:17assert.commandWorked@src/mongo/shell/assert.js:618:16commitTransaction@src/mongo/shell/session.js:929:17@(shell):1:1// 这儿又抽风了,内部回滚之后禁止提交操作,尝试进行回滚,结果说已经提交了,不能回滚,真是晕死[10.240.129.36:30001_primary@dba]> session.abortTransaction()2018-06-30T15:06:04.162+0800 E QUERY [js] Error: Cannot call abortTransaction after calling commitTransaction. :abortTransaction@src/mongo/shell/session.js:764:1abortTransaction@src/mongo/shell/session.js:934:17@(shell):1:1第三次尝试(成功提交):
[10.240.129.36:30001_primary@admin]> session=db.getMongo().startSession()session { "id" : UUID("e7935985-160d-4969-adfe-3bae401e155f") }[10.240.129.36:30001_primary@admin]> session.startTransaction()[10.240.129.36:30001_primary@admin]> coll_1=session.getDatabase('dba').coll_1dba.coll_1[10.240.129.36:30001_primary@admin]> coll_2=session.getDatabase('dba').coll_2;dba.coll_2[10.240.129.36:30001_primary@admin]> coll_1.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b373202d0b208b7386e9c20")}[10.240.129.36:30001_primary@admin]> coll_2.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b373202d0b208b7386e9c21")}[10.240.129.36:30001_primary@admin]> session.commitTransaction()[10.240.129.36:30001_primary@admin]> use dbaswitched to db dba[10.240.129.36:30001_primary@dba]> db.coll_1.find(){ "_id" : ObjectId("5b371e120d6160b73a9fcee6"), "test" : true }{ "_id" : ObjectId("5b371e6d0d6160b73a9fcee7"), "test" : true }{ "_id" : ObjectId("5b373202d0b208b7386e9c20"), "not_test" : false }[10.240.129.36:30001_primary@dba]> db.coll_2.find(){ "_id" : ObjectId("5b373202d0b208b7386e9c21"), "not_test" : false }第四次尝试(测试回滚):
[10.240.129.36:30001_primary@admin]> session=db.getMongo().startSession()session { "id" : UUID("e7935985-160d-4969-adfe-3bae401e155f") }[10.240.129.36:30001_primary@admin]> session.startTransaction()[10.240.129.36:30001_primary@admin]> coll_1=session.getDatabase('dba').coll_1dba.coll_1[10.240.129.36:30001_primary@admin]> coll_2=session.getDatabase('dba').coll_2;dba.coll_2[10.240.129.36:30001_primary@admin]> coll_1.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b373202d0b208b7386e9c20")}[10.240.129.36:30001_primary@admin]> coll_2.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b373202d0b208b7386e9c21")}[10.240.129.36:30001_primary@admin]> session.commitTransaction()[10.240.129.36:30001_primary@admin]> use dbaswitched to db dba[10.240.129.36:30001_primary@dba]> db.coll_1.find(){ "_id" : ObjectId("5b371e120d6160b73a9fcee6"), "test" : true }{ "_id" : ObjectId("5b371e6d0d6160b73a9fcee7"), "test" : true }{ "_id" : ObjectId("5b373202d0b208b7386e9c20"), "not_test" : false }[10.240.129.36:30001_primary@dba]> db.coll_2.find(){ "_id" : ObjectId("5b373202d0b208b7386e9c21"), "not_test" : false }[10.240.129.36:30001_primary@dba]> session=db.getMongo().startSession()session { "id" : UUID("cc0e2d23-1766-4ea5-87a5-957efcae28ad") }[10.240.129.36:30001_primary@dba]> session.startTransaction()[10.240.129.36:30001_primary@dba]> coll_1=session.getDatabase('dba').coll_1dba.coll_1[10.240.129.36:30001_primary@dba]> coll_2=session.getDatabase('dba').coll_2;dba.coll_2[10.240.129.36:30001_primary@dba]> coll_1.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b3732f0d0b208b7386e9c22")}[10.240.129.36:30001_primary@dba]> coll_2.insertOne({'not_test':false}){ "acknowledged" : true, "insertedId" : ObjectId("5b3732f1d0b208b7386e9c23")}[10.240.129.36:30001_primary@dba]> session.abortTransaction()[10.240.129.36:30001_primary@dba]> db.coll_2.find(){ "_id" : ObjectId("5b373202d0b208b7386e9c21"), "not_test" : false }[10.240.129.36:30001_primary@dba]> db.coll_1.find(){ "_id" : ObjectId("5b371e120d6160b73a9fcee6"), "test" : true }{ "_id" : ObjectId("5b371e6d0d6160b73a9fcee7"), "test" : true }{ "_id" : ObjectId("5b373202d0b208b7386e9c20"), "not_test" : false }注意
默认事务超时时间有点短,1分钟
默认锁等待时间短,5毫秒
事务的操作有些繁琐,不如RDS的 begin commit rollback方便(指SHELL操作)
一个事务的对应的oplog不能超过16M(指BSON格式的文件大小)
显式事务功能的开启对WT缓存提出了新的要求。类似于IBP事务不按时提交,类似undo用于存放快照或者旧版本的东西肯定会占用大量WT的空间。
事务
尝试
版本
文档
兼容性
肯定
测试
必要
周期
对象
文件
时间
生命
结果
一致
繁琐
一致性
不好
东西
之间
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
云南咖啡
精品咖啡豆
互联网巨头反垄断金融科技
互联网科技开发公司
唐信互联网科技
互联网科技论文
互联网科技缩写
美国互联网黑科技
上海万想互联网科技
互联网高科技企业
成都玖崟互联网科技有限公司乐商圈怎么样
全球顶尖互联网科技公司
崇明区互联网教育科技诚信经营
未来五年的互联网科技
佛山市翊博互联网络科技有限公司
工业互联网展湾科技股份有限公司
产业互联网科技服务公司
科技互联网专业工作会议发言稿
北京品多多互联网科技有限公司
伍佰万互联网科技是干嘛的
北京互联网科技有限公司
腾讯科技 互联网女皇
兼蜜互联网科技
四个字互联网科技公司取名
青岛中康互联网医疗科技有限公司
岳阳华臻互联网科技有限公司
宝灵互联网科技有限公司
众安科技工业互联网合作
现代互联网科技公司
利用互联网等科技手段