问题
Currently, we have an orderId for which we give the benefit(posting) to the user. There are multiple events that can trigger benefit/posting. But the condition is that only 1 event should be triggered. Hence for handling current requests, we created a boolean field POSTING_EVENT_SENT, initially set to false, and later whoever was able to mark it as true can proceed further.
public boolean isOrderLockedAndUpdatedToTriggerPosting(String orderId, OrderStatus orderStatus) {
Query query = new Query();
query.addCriteria(Criteria.where(OrderConstants.ORDER_ID).is(orderId));
query.addCriteria(Criteria.where(OrderConstants.POSTING_EVENT_SENT).is(false));
Update update = new Update();
update.set(OrderConstants.ORDER_STATUS, orderStatus);
update.set(OrderConstants.UPDATED_AT, new Date());
update.set(OrderConstants.UPDATED_IP_BY, deploymentProperties.getServerIp());
update.set(OrderConstants.POSTING_EVENT_SENT, true);
update.set(OrderConstants.UPDATED_BY, OrderConstants.UPDATED_BY_WORKER);
UpdateResult result = mongoTemplate.updateFirst(query, update, OrderDetails.class);
return result.getModifiedCount() > 0;
}
this is the mongodb query that code is trying to execute
db.order.update({orderId : 123, paymentEventSent: false},{$set : {paymentEventSent: true}})
So we're checking if the field is false, then mark it to true. So theoretically only 1 request will be able to do the same, because the mongo queries are atomic. But in our scenario, both the concurrent queries were updating the records successfully. What else we're missing here?
回答1:
Use conditional updates and examine the number of updated documents to see if the update happened.
require 'mongo'
client = Mongo::Client.new(['localhost:14400'])
coll = client['coll']
coll.delete_many
coll.insert_one(foo: 1)
rv = coll.update_one({foo: 1}, '$set' => {foo: 2})
if rv.modified_count == 1
puts 'Updated'
end
rv = coll.update_one({foo: 1}, '$set' => {foo: 2})
if rv.modified_count == 1
puts 'Updated'
end
https://github.com/p-mongo/tests/blob/master/query-conditional-update/test.rb
来源:https://stackoverflow.com/questions/65915366/mongodb-concurrent-update-to-same-document-is-not-behaving-atomic