Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-3217

$push and $pushAll oplog is not idempotent

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 1.8.1
    • Component/s: None
    • None
    • Fully Compatible
    • ALL

      Run following commands on replica set:

      replica:PRIMARY> db.foo.insert(

      {"_id":"test", x:[1, 2, 3]}

      )
      replica:PRIMARY> db.foo.update(

      {"_id":"test"}

      , {$pushAll: {x:[4]}})
      replica:PRIMARY> db.foo.update(

      {"_id":"test"}

      , {$pull: {x:1}})
      replica:PRIMARY> db.foo.find(

      {"_id":"test"}

      )

      { "_id" : "test", "x" : [ 2, 3, 4 ] }

      View oplog:

      { "ts" :

      { "t" : 1307521384000, "i" : 1 }

      , "h" : NumberLong("-2482281928928604340"), "op" : "i", "ns" : "points.foo", "o" :

      { "_id" : "test", "x" : [ 1, 2, 3 ] }

      }
      { "ts" :

      { "t" : 1307521392000, "i" : 1 }

      , "h" : NumberLong("9215593517142594101"), "op" : "u", "ns" : "points.foo", "o2" : { "_id" : "test", "x" :

      { "$size" : 3 }

      }, "o" : { "$pushAll" :

      { "x" : [ 4 ] }

      } }
      { "ts" :

      { "t" : 1307521404000, "i" : 1 }

      , "h" : NumberLong("-4865163357721582816"), "op" : "u", "ns" : "points.foo", "o2" :

      { "_id" : "test" }

      , "o" : { "$pull" :

      { "x" : 1 }

      } }

      Now let's reexecute last two commands from oplog. They must be idempotent so after execution database content must not change:

      replica:PRIMARY> db.foo.update({ "_id" : "test", "x" :

      { "$size" : 3 }

      }, { "$pushAll" :

      { "x" : [ 4 ] }

      })
      replica:PRIMARY> db.foo.update(

      { "_id" : "test" }

      , { "$pull" :

      { "x" : 1 }

      })
      replica:PRIMARY> db.foo.find(

      {"_id":"test"}

      )

      { "_id" : "test", "x" : [ 2, 3, 4, 4 ] }

      But it changes. Because $pushAll was not rewritten in idempotent way.

      If you change $pushAll with $push the same example would work. Corresponding oplog message is:

      { "ts" :

      { "t" : 1307521870000, "i" : 1 }

      , "h" : NumberLong("-6895072222265747191"), "op" : "u", "ns" : "points.foo", "o2" : { "_id" : "test2", "x" :

      { "$size" : 3 }

      }, "o" : { "$push" :

      { "x" : 4 }

      } }

      again mongo tests only array size.

            Assignee:
            Unassigned Unassigned
            Reporter:
            kibergus Alexey Guseynov
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: