In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)06/01 Report--
This paper gives an example to describe the method of realizing transaction by two-phase commit in MongoDB database. Share with you for your reference, the details are as follows:
Manipulating a single document in an MongoDB database is always atomic. However, operations that involve multiple documents are usually treated as a "transaction" rather than atomic. Because documents can be quite complex and contain multiple nested documents, the atomicity of a single document supports many practical use cases. Although single document operations are atomic, in some cases, multiple document transactions are required. In these cases, two-phase commit is used to provide these types of multi-document update support. Because documents can be represented as Pending data and state, a two-phase commit can be used to ensure that the data is consistent, and in the case of an error, the pre-transaction state is recoverable.
The most common example of a transaction is a reliable transfer from account A to account B. in a relational database, this operation encapsulates the amount subtracted from account An and the amount added to account B in a single atomic transaction. In MongoDB, two-phase commit can be used to achieve the same effect. All the examples in this article use mongo shell to interact with the database and assume that there are two collections: first, a collection named accounts stores document data for each account, and another collection named transactions stores the transaction itself.
First create two accounts named An and B, using the following command:
Db.accounts.save ({name: "A", balance: 1000, pendingTransactions: []}) db.accounts.save ({name: "B", balance: 1000, pendingTransactions: []})
Use the find () method to verify that the two operations have been successful:
Db.accounts.find ()
Mongo returns two documents similar to the following:
{"_ id": ObjectId ("4d7bc66cb8a04f512696151f"), "name": "A", "balance": 1000, "pendingTransactions": []} {"_ id": ObjectId ("4d7bc67bb8a04f5126961520"), "name": "B", "balance": 1000, "pendingTransactions": []}
Transaction process:
Set the transaction initial state initial:
Create the transaction collection by inserting the following document, which holds the source (source) and destination (destination), which are referenced from the field names of the accounts collection document, and the value field represents data that changes the number of balance fields. Finally, the state field reflects the current state of the transaction.
The copy code is as follows: db.transactions.save ({source: "A", destination: "B", value: 100, state: "initial"})
Verify that the operation is successful, using find ():
Db.transactions.find ()
This operation returns a document similar to the following:
The copy code is as follows: {"_ id": ObjectId ("4d7bc7a8b8a04f5126961522"), "source": "A", "destination": "B", "value": 100, "state": "initial"}
Switch the transaction to the Pending state:
Set the transaction state from initial to pending before modifying the accounts collection record. Use the findOne () method to assign the transaction document to the local variable t in the shell session:
T = db.transactions.findOne ({state: "initial"})
After the variable t is created, shell will return its value and you will see the following output:
The copy code is as follows: {"_ id": ObjectId ("4d7bc7a8b8a04f5126961522"), "source": "A", "destination": "B", "value": 100, "state": "initial"}
Use update () to change the value of state to pending:
Db.transactions.update ({_ id: t._id}, {$set: {state: "pending"}}) db.transactions.find ()
The find () operation returns the contents of the transaction collection, similar to the following:
The copy code is as follows: {"_ id": ObjectId ("4d7bc7a8b8a04f5126961522"), "source": "A", "destination": "B", "value": 100, "state": "pending"}
Apply the transaction to two accounts:
Use the update () method to apply transactions to two accounts. In the update () query, the condition pendingTransactions: {$ne:t._id} prevents the transaction from updating the account if the account's pendingTransaction field contains the _ id of transaction t:
Db.accounts.update ({name: t.source, pendingTransactions: {$ne: t._id}}, {$inc: {balance:-t.value}, $push: {pendingTransactions: t._id}}) db.accounts.update ({name: t.destination, pendingTransactions: {$ne: t._id}}, {$inc: {balance: t.value}, $push: {pendingTransactions: t._id}}) db.accounts.find ()
The find () operation will return the contents of the accounts collection, which should now look like this:
{"_ id": ObjectId ("4d7bc97fb8a04f5126961523"), "balance": 900, "name": "A", "pendingTransactions": [ObjectId ("4d7bc7a8b8a04f5126961522")]} {"_ id": ObjectId ("4d7bc984b8a04f5126961524"), "balance": 1100, "name": "B", "pendingTransactions": [ObjectId ("4d7bc7a8b8a04f5126961522")]}
Set the transaction status to committed:
Use the following update () operation to set the status of the transaction to committed:
Db.transactions.update ({_ id: t._id}, {$set: {state: "committed"}}) db.transactions.find ()
The find () operation sends back the contents of the transactions collection, which should now look like this:
The copy code is as follows: {"_ id": ObjectId ("4d7bc7a8b8a04f5126961522"), "destination": "B", "source": "A", "state": "committed", "value": 100}
Remove the pending transaction:
Use the following update () operation to remove the pending transaction from the accounts collection:
Db.accounts.update ({name: t.source}, {$pull: {pendingTransactions: t._id}}) db.accounts.update ({name: t.destination}, {$pull: {pendingTransactions: t._id}}) db.accounts.find ()
The find () operation returns the contents of the accounts collection, which should now look like this:
{"_ id": ObjectId ("4d7bc97fb8a04f5126961523"), "balance": 900, "name": "A", "pendingTransactions": []} {"_ id": ObjectId ("4d7bc984b8a04f5126961524"), "balance": 1100, "name": "B", "pendingTransactions": []}
Set the transaction status to done:
Complete the transaction by setting the state of the transaction document to done:
Db.transactions.update ({_ id: t._id}, {$set: {state: "done"}}) db.transactions.find ()
The find () operation returns the contents of the transaction collection, which should look like this:
The copy code is as follows: {"_ id": ObjectId ("4d7bc7a8b8a04f5126961522"), "destination": "B", "source": "A", "state": "done", "value": 100}
Recover from a failure scenario:
The most important part is not the typical example above, but the possibility of recovering unfinished transactions from various failure scenarios. This section outlines possible failures and provides ways to recover transactions from these events. There are two types of failures:
1. All failures that occur after the first step (that is, setting the initial state of the transaction initial) but before the third step (that is, applying the transaction to two accounts). In order to restore the transaction, the application should get a transaction list of pending states and recover from the second step (that is, switching transactions to pending state).
2. All failures that occur after step 3 (that is, applying transactions to two accounts) but before step 5 (that is, setting the transaction status to done). In order to restore the transaction, the application needs to get a list of transactions in the committed state and recover from the fourth step (that is, removing the pending transaction).
As a result, the application is always able to recover the transaction and eventually reach a consistent state. Run the following restore operation when the application begins to capture each outstanding transaction. You may also want to run recovery operations regularly to ensure that the data is in a consistent state. The time it takes to reach an agreed state depends on how long it takes the application to recover each transaction.
Roll back:
In some cases, you may need to "roll back" or "undo" a transaction, either when the application needs to "cancel" the transaction, or because it always needs to recover when one of the accounts does not exist, or to stop an existing transaction. There are two possible rollback operations:
1. After applying the transaction (that is, step 3), you have fully committed the transaction and you should not roll back the transaction. Instead, create a new transaction and switch the values of the source (source) and destination (destination).
2. After creating the transaction (that is, the first step), before applying the transaction (that is, step 3), use the following process:
Set the transaction status to canceling:
First set the transaction state to canceling, using the following update () operation:
Db.transactions.update ({_ id: t._id}, {$set: {state: "canceling"}})
Undo the transaction:
Use the following action order to undo transactions from two accounts:
Db.accounts.update ({name: t.source, pendingTransactions: t._id}, {$inc: {balance: t.value}, $pull: {pendingTransactions: t._id}}) db.accounts.update ({name: t.destination, pendingTransactions: t._id}, {$inc: {balance:-t.value}, $pull: {pendingTransactions: t._id}}) db.accounts.find ()
The find () operation returns the contents of the acounts collection, which should look like this:
{"_ id": ObjectId ("4d7bc97fb8a04f5126961523"), "balance": 1000, "name": "A", "pendingTransactions": []} {"_ id": ObjectId ("4d7bc984b8a04f5126961524"), "balance": 1000, "name": "B", "pendingTransactions": []}
Set the transaction status to canceled:
Finally, set the transaction state to canceled using the following update () state:
Db.transactions.update ({_ id: t._id}, {$set: {state: "canceled"}})
Reference: http://docs.mongodb.org/manual/tutorial/perform-two-phase-commits/
It is hoped that what is described in this article will be helpful to the programming of MongoDB database.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.