【MongoDB】4.0版本事务上手测试
发表于:2025-11-12 作者:千家信息网编辑
千家信息网最后更新 2025年11月12日,事务上手测试基础:原来3版本的只能叫单文档事务,即针对行的事务。所以没必要显式提供调用,多文档事务由于有损耗,照顾到性能的需求,提供了事务开启关闭的接口。多行,多集合,多库之间读肯定会牵扯到一致性读,
千家信息网最后更新 2025年11月12日【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安全错误
数据库的锁怎样保障安全
最全的植物数据库
企业安全生产风险数据库
互联网金融如何科技创新
武汉创美软件开发公司
软件开发外包公司好不好
浙江现代软件开发
软件开发去哪个学校学
数据库程序编辑软件
网络安全保障行动方案
学编程软件开发学费多少
数据库识别锁
计算机网络技术大连理工大学
java电商服务器
黑客攻防与网络安全训练
烟雨小镇服务器bgm
漳州软件开发上市公司
自学计算机软件开发
中山无限软件开发报价表
谁要服务器
浪潮服务器配置管理口
魔兽世界服务器丽丽
纽瑞科技 互联网
软件开发云的优势
下载阿里巴巴网络安全卫士
网络安全工程师零基础要学哪些
虚拟数据库数据共享
软件开发外包会计核算
袁家军 网络安全和信息化
手机wps输入完整数据库
简易的网络安全主题的手抄报