- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
Use multi-document ACID transactions in MongoDB 4.0
MongoDB 4.0最终支持多文档ACID事务。在演示过程中,我们将讨论什么是事务,什么是ACID属性。
我们将展示如何使用MongoDB中的事务来做一些实际的示例,并讨论优缺点和当前的限制。
展开查看详情
1 .Use multi-document ACID transactions in MongoDB 4.0 November 7th 2018 Corrado Pandiani - Senior consultant Percona
2 . Use multi-document ACID transactions in MongoDB 4.0 Thank You Sponsors!!
3 . Use multi-document ACID transactions in MongoDB 4.0 About me ● Italian (yes, I love spaghetti, pizza and espresso) ● 22 years spent in designing, developing and administering web sites, mainly in the football industry ● Joined Percona on February 2018 as a Senior Consultant really sorry for my face ● MySQL / MongoDB DBA ● Perl/PHP/Javascript developer (but also some other languages) ● Open Source enthusiast ● 1 wife, 3 male kids, 1 maltese dog, 2 goldfishes ● Piano, synthesizers, pipe organ and bass guitar player
4 . Use multi-document ACID transactions in MongoDB 4.0 What is a transaction ● Legacy feature in relational databases ● A transaction symbolizes a unit of work performed within a database management system (or similar system) against a all or nothing database, and treated in a coherent and reliable way independent of other transactions. A transaction generally represents any change in a database. (Wikipedia)
5 . Use multi-document ACID transactions in MongoDB 4.0 ACID ● Atomicity : guarantees that each transaction is treated as a single "unit", which either succeeds completely, or fails completely ● Consistency : ensures that a transaction can only bring the database from one valid state to another ● Isolation : ensures that concurrent execution of transactions leaves the database in the same state that would have been obtained if the transactions were executed sequentially ● Durability : guarantees that once a transaction has been committed, it will remain committed even in the case of a system failure
6 . Use multi-document ACID transactions in MongoDB 4.0 MongoDB 4.0 - transactions ● First release to provide multi-document ACID transactions ● New concept for a document-based database ● Multi-document transactions are available for Replica Sets only new amazing features ○ standalone as well, but you need to configure it as RS ● Multi-document transactions for sharded clusters are not available. Scheduled for version 4.2 ● Multi-document transactions are available for WiredTiger storage engine only
7 . Use multi-document ACID transactions in MongoDB 4.0 MongoDB 4.0 - transactions ● A transaction executes only on the PRIMARY ● In-memory ● After committing the replication takes place as usual ● Journal must be enabled for durability new amazing features ○ Always enabled in any case ● Isolation is guaranteed by WiredTiger snapshot ● Setting WriteConcern to majority is required for data consistency ● Exclusive locks on the documents
8 . Use multi-document ACID transactions in MongoDB 4.0 Important notes ● Multi-document transaction incurs a greater performance cost over single document writes ● Multi-document transactions should not be a replacement for effective schema design ● For many scenarios, modeling your data appropriately will minimize the need for multi-document transactions, denormalized data model will continue to be optimal ● Remember that single document writes are atomic
9 . Use multi-document ACID transactions in MongoDB 4.0 Limitations ● A collection MUST exists in order to use transactions ● A collection cannot be created or dropped inside a transaction ● An index cannot be created or dropped inside a transaction ● Non-CRUD operations cannot be used inside a transaction; for example stuffs like createUser, getParameter, etc. ● Cannot read/write in config, admin and local databases ● Cannot write to system.* collections
10 . Use multi-document ACID transactions in MongoDB 4.0 Limitations ● A single transaction is limited to 16MB ○ The same for BSON objects and oplog entries ○ Larger transactions need to be splitted into smaller transactions
11 . Use multi-document ACID transactions in MongoDB 4.0 Is my app good for transactions ? ● Yes it is if ○ you have a lot of 1:N and/or N:N relationships between different collections ○ you are aware of data consistency because your app needs to be ○ You manage commercial/financial or really sensitive data ● No it’s not if ○ you shouldn’t be aware of data consistency ○ you can achieve as well your goals embedding documents and denormalizing
12 . Use multi-document ACID transactions in MongoDB 4.0 Sessions ● Transactions are associated with a session ● In order to use a transaction you must create a session at first ● When using a driver to connect to mongod, the session id must be passed to each operation in the transaction ● At any given time you can have only a single open transaction ● If a session ends for any reason the open transaction is automatically aborted ● Sessions were introduced in version 3.6
13 . Use multi-document ACID transactions in MongoDB 4.0 Commands available ● Session.startTransaction() ○ Starts a multi-document transaction associated with the session ● Session.commitTransaction() ○ Saves the changes made by the operations in the multi- document transaction and ends the transaction ● Session.abortTransaction() ○ The transaction ends without saving any of the changes made by the operations in the transaction
14 . Use multi-document ACID transactions in MongoDB 4.0 Our first transaction
15 . Use multi-document ACID transactions in MongoDB 4.0 Start mongod ● Start your Replica Set environment ● Even with a standalone host the Replica Set must be configured and initiated #> mongod --dbpath /data/db40 --logpath /data/log40.log -- fork --replSet foo
16 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: create a collection and insert data foo:PRIMARY> use percona switched to db percona foo:PRIMARY> db.createCollection('ple18') { "ok" : 1, "operationTime" : Timestamp(1538483120, 1), "$clusterTime" : { "clusterTime" : Timestamp(1538483120, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } } foo:PRIMARY> db.ple18.insert([{_id:1, name:"Corrado"},{_id:2, name:"Peter"},{_id:3, name:"Heidi"}]) BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 3, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
17 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: create a transaction and insert a new document foo:PRIMARY> session = db.getMongo().startSession() session { "id" : UUID("dcfa7de5-527d-4b1c-a890-53c9a355920d") } foo:PRIMARY> session.startTransaction() foo:PRIMARY> session.getDatabase("percona").ple18.insert([{_id: 4 , name : "George"},{_id: 5, name: "Tom"}]) WriteResult({ "nInserted" : 2 })
18 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: read the documents from the collection foo:PRIMARY> session.getDatabase("percona").ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi" } { "_id" : 4, "name" : "George" } { "_id" : 5, "name" : "Tom" } foo:PRIMARY> db.ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi" } The transaction is not yet committed: inserted and updated documents are visible only inside the session. Even in the same connection.
19 . Use multi-document ACID transactions in MongoDB 4.0 Connection #2: open a new connection and read the documents foo:PRIMARY> use percona switched to db percona foo:PRIMARY> db.ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi" }
20 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: commit the transaction foo:PRIMARY> session.commitTransaction() foo:PRIMARY> session.getDatabase("percona").ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi" } { "_id" : 4, "name" : "George" } { "_id" : 5, "name" : "Tom" } foo:PRIMARY> db.ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi" } { "_id" : 4, "name" : "George" } { "_id" : 5, "name" : "Tom" }
21 . Use multi-document ACID transactions in MongoDB 4.0 Connection #2: read the collection foo:PRIMARY> db.ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi" } { "_id" : 4, "name" : "George" } { "_id" : 5, "name" : "Tom" } Now we can see the effect of the committed transaction in all other connections.
22 . Use multi-document ACID transactions in MongoDB 4.0 Isolation test
23 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: create a new transaction for updating data foo:PRIMARY> var session1 = db.getMongo().startSession() foo:PRIMARY> session1.startTransaction() foo:PRIMARY> session1.getDatabase("percona").ple18.update({_id:3},{$set:{ gender: "F" }}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) foo:PRIMARY> session1.getDatabase("percona").ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi", "gender" : "F" } { "_id" : 4, "name" : "George" } { "_id" : 5, "name" : "Tom" }
24 . Use multi-document ACID transactions in MongoDB 4.0 Connection #2: create a new transaction for updating data foo:PRIMARY> var session2 = db.getMongo().startSession() foo:PRIMARY> session2.startTransaction() foo:PRIMARY> session2.getDatabase("percona").ple18.update({_id:{$in: [1,2,4,5]}},{$set:{ gender: "M" }},{multi:"true"}) WriteResult({ "nMatched" : 4, "nUpserted" : 0, "nModified" : 4 }) foo:PRIMARY> session2.getDatabase("percona").ple18.find() { "_id" : 1, "name" : "Corrado", "gender" : "M" } { "_id" : 2, "name" : "Peter", "gender" : "M" } { "_id" : 3, "name" : "Heidi" } { "_id" : 4, "name" : "George", "gender" : "M" } { "_id" : 5, "name" : "Tom", "gender" : "M" }
25 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: commit the transaction foo:PRIMARY> session1.commitTransaction() foo:PRIMARY> session1.getDatabase("percona").ple18.find() { "_id" : 1, "name" : "Corrado" } { "_id" : 2, "name" : "Peter" } { "_id" : 3, "name" : "Heidi", "gender" : "F" } { "_id" : 4, "name" : "George" } { "_id" : 5, "name" : "Tom" }
26 . Use multi-document ACID transactions in MongoDB 4.0 Connection #2: commit the transaction foo:PRIMARY> session2.commitTransaction() foo:PRIMARY> session2.getDatabase("percona").ple18.find() { "_id" : 1, "name" : "Corrado", "gender" : "M" } { "_id" : 2, "name" : "Peter", "gender" : "M" } { "_id" : 3, "name" : "Heidi", "gender" : "F" } { "_id" : 4, "name" : "George", "gender" : "M" } { "_id" : 5, "name" : "Tom", "gender" : "M" }
27 . Use multi-document ACID transactions in MongoDB 4.0 Conflicts
28 . Use multi-document ACID transactions in MongoDB 4.0 Connection #1: create a new transaction for updating data Let’s try to create two concurrent transaction that modify the same document foo:PRIMARY> session.startTransaction() foo:PRIMARY> session.getDatabase("percona").ple18.update({name:"Heidi"},{$set:{na me:"Luise"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
29 . Use multi-document ACID transactions in MongoDB 4.0 Connection #2: create a new transaction for updating data Let’s try to modify the same document. The conflict is triggered before the commit. foo:PRIMARY> session.startTransaction() foo:PRIMARY> session.getDatabase("percona").ple18.update({name:"Heidi"},{$set:{name:"Marie"}}) WriteCommandError({ "errorLabels" : [ "TransientTransactionError" ], "operationTime" : Timestamp(1538495683, 1), "ok" : 0, "errmsg" : "WriteConflict", "code" : 112, "codeName" : "WriteConflict", "$clusterTime" : { "clusterTime" : Timestamp(1538495683, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } })