-
Type: Bug
-
Resolution: Duplicate
-
Priority: 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(
, {$pushAll: {x:[4]}})
replica:PRIMARY> db.foo.update(
, {$pull: {x:1}})
replica:PRIMARY> db.foo.find(
)
{ "_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" :
, "h" : NumberLong("9215593517142594101"), "op" : "u", "ns" : "points.foo", "o2" : { "_id" : "test", "x" :
{ "$size" : 3 }}, "o" : { "$pushAll" :
{ "x" : [ 4 ] } } }
{ "ts" :
, "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(
, { "$pull" :
{ "x" : 1 } })
replica:PRIMARY> db.foo.find(
)
{ "_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.
- duplicates
-
SERVER-3407 oplog is not idempotent for array operators, which could lead to silent data corruption (without journalling)
- Closed
- is related to
-
SERVER-5961 $push array size constraint can cause incorrect replication of another field during initial sync
- Closed