问题
Account has embedded
Transactions
amount (positive for received transactions, negative for outgoing transactions)
User wants to send money. We need to compute account's balance to check if there is enough money. In pseudocode:
send_money(amount)
balance = sum(account's all transactions) // Mongo Query 1
if (amount <= balance)
add a new transaction to account // Mongo Query 2
But isn't it possible that two concurrent mongo connections both pass Query 1 and proceed to make Query 2? Say user's balance is 1 and two concurrent send money requests worth of 1 come at the same time passing Query 1 and are successfully added to transactions. In effect, the user ends up with a balance of -1.
How is this prevented?
回答1:
When your use-case requires transactions which span multiple documents, MongoDB is usually a bad fit for it, because it doesn't support atomic operations when more than one document is affected.
A possible workaround is the two-phase-commit model.
It basically means that you first add a description what you want to do to each document as an additional field to it. Then you perform an atomic operation on each document which applies that action and removes the description. Each of these steps is confirmed by querying the document afterwards and each step of the transaction is documented by a 3rd document in an additional collection of pending transactions. This allows you to check for pending transactions and roll them back.
This method is hard to implement and has considerable overhead. Before you implement this, you should really consider if there is really a good reason no to use a database system with native transaction support.
回答2:
How about using the Update If Current pattern outlined here: http://docs.mongodb.org/manual/tutorial/isolate-sequence-of-operations/ with perhaps the suggestion "Add a version variable to the document that applications increment upon each update operation" discussed near the base of that page? You will probably need to track the current balance in a field in the document in addition to the array of transactions. So your update section will likely require an $inc of 1 on your version field, an $inc of the +/- amount on the balance field and a $push for the new transaction element in the array.
回答3:
This will not be a problem anymore beyond next summer. MongoDB will add support for multi-document transactions in version 4.0, so we will have ACID guarantees in multi-document transactions like in RBDMS systems.
Now, MongoDB use cases will fit all those you can work with!
Check this post: https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb?jmp=community
来源:https://stackoverflow.com/questions/20145043/how-to-move-money-with-mongodb