MongoDB concurrent update to same document is not behaving atomic

无人久伴 提交于 2021-02-11 06:55:31

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!