原來3版本的只能叫單文檔事務,即針對行的事務。因此不必顯式提供調用,多文檔事務因爲有損耗,照顧到性能的需求,提供了事務開啓關閉的接口。
多行,多集合,多庫之間讀確定會牽扯到一致性讀,因此多文檔事務確定是有必要的。
4.2版本可能會支持分片系統多文檔事務,4.0的多文檔事務最多隻面向複製集javascript
集合:java
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_1 coll_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秒,超出後會被自動清理sql
// 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中進行設置後,再次插入,提示事務不存在mongodb
[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:48 Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1 Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21 DBCollection.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:48 Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1 Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21 DBCollection.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:1 startTransaction@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_1 dba.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:48 Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1 Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21 DBCollection.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:48 Bulk/executeBatch@src/mongo/shell/bulk_api.js:902:1 Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21 DBCollection.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:1 startTransaction@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:13 throwOrReturn@src/mongo/shell/explainable.js:31:1 constructor/this.finish@src/mongo/shell/explain_query.js:171:24 constructor/this.shellPrint@src/mongo/shell/explain_query.js:210:26 shellPrintHelper@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:13 doassert@src/mongo/shell/assert.js:18:14 _assertCommandWorked@src/mongo/shell/assert.js:534:17 assert.commandWorked@src/mongo/shell/assert.js:618:16 commitTransaction@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:13 doassert@src/mongo/shell/assert.js:18:14 _assertCommandWorked@src/mongo/shell/assert.js:534:17 assert.commandWorked@src/mongo/shell/assert.js:618:16 commitTransaction@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:1 abortTransaction@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_1 dba.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 dba switched 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_1 dba.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 dba switched 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_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}) { "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的空間。shell