【MongoDB】4.0版本事务上手测试
发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,事务上手测试基础:原来3版本的只能叫单文档事务,即针对行的事务。所以没必要显式提供调用,多文档事务由于有损耗,照顾到性能的需求,提供了事务开启关闭的接口。多行,多集合,多库之间读肯定会牵扯到一致性读,
千家信息网最后更新 2025年02月23日【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安全错误
数据库的锁怎样保障安全
福建视频云空间技术服务器
宽带网络安全设置
中国最厉害的软件开发
互联网直播管理服务器
数据库 小型超市管理系统
bmj 数据库
网络安全防护维护
如何将数据库设置为私有云
以网络安全为主题的宣传语
河北环保软件开发影响
贵阳 软件开发招聘
软件开发及培训
ibm 服务器客服电话
加强网络安全人才队伍建设
阿里云服务器续费贵
窦超网络技术
mes系统是服务器吗
原神不同服务器的叫法
软件开发学校好还是培训班好
数据库实体图关系符号解释
上海健康云数据库供应商
os服务器已经开放的端口
bmj 数据库
系统软件开发中设备入账
软件开发的比赛
龙华网络安全建设哪家好
苹果手机无法安全连接服务器
数据库查询最贵的三本图书信息
网上怎么倒卖服务器
网络安全CS是指