I was able to easily setup and execute a scenario where reasonable
clock skew (10 minute difference) was not compensated (i.e. data loss
occurs):
1. Setup of A, B and C nodes. Each of B and C are about 10 minutes
behind A.
// On A
>date returns Mon May 23 19:54:34 UTC 2011
// On B
>date return Mon May 23 19:43:33 UTC 2011
2. Cluster runs with A as primary. Insert a few records as follows:
db.foo.insert({x:1})
db.foo.insert({x:2})
// On A
rs1:PRIMARY> db.foo.find()
{ "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 }
{ "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 }
rs1:PRIMARY> use local
switched to db local
rs1:PRIMARY> db.oplog.rs.find()
{ "ts" : { "t" : 1306180706000, "i" : 1 }, "h" : NumberLong(0), "op" :
"n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : { "t" : 1306180747000, "i" : 1 }, "h" :
NumberLong("3136340678959693841"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 } }
{ "ts" : { "t" : 1306180751000, "i" : 1 }, "h" :
NumberLong("-3548970921664408588"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 } }
B and C returns the exact same output for both foo and
oplog.rs
collections.
3. Now terminate node A using db.shutdownServer(). B gets promoted as
primary. Insert a few records again now (on B):
db.foo.insert({y:1})
db.foo.insert({y:2})
// On B
rs1:PRIMARY> db.foo.find()
{ "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 }
{ "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 }
{ "_id" : ObjectId("4ddabb630cc90e0d72223b68"), "y" : 1 }
{ "_id" : ObjectId("4ddabb680cc90e0d72223b69"), "y" : 2 }
rs1:PRIMARY> use local
switched to db local
rs1:PRIMARY> db.oplog.rs.find()
{ "ts" : { "t" : 1306180706000, "i" : 1 }, "h" : NumberLong(0), "op" :
"n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : { "t" : 1306180747000, "i" : 1 }, "h" :
NumberLong("3136340678959693841"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 } }
{ "ts" : { "t" : 1306180751000, "i" : 1 }, "h" :
NumberLong("-3548970921664408588"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 } }
{ "ts" : { "t" : 1306180451000, "i" : 1 }, "h" :
NumberLong("-5215459932265573458"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabb630cc90e0d72223b68"), "y" : 1 } }
{ "ts" : { "t" : 1306180456000, "i" : 1 }, "h" :
NumberLong("-8690927360367643972"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabb680cc90e0d72223b69"), "y" : 2 } }
You can see that the ts are not in increasing order anymore. The ts of
{y:1} insert is less than that of {x:2} insert.
C does not register these new inserts at all.
// On C
rs1:SECONDARY> db.foo.find()
{ "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 }
{ "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 }
rs1:SECONDARY> db.oplog.rs.find()
{ "ts" : { "t" : 1306180706000, "i" : 1 }, "h" : NumberLong(0), "op" :
"n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : { "t" : 1306180747000, "i" : 1 }, "h" :
NumberLong("3136340678959693841"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 } }
{ "ts" : { "t" : 1306180751000, "i" : 1 }, "h" :
NumberLong("-3548970921664408588"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 } }
No change in both these collections on C even though writes are being
made on PRIMARY B and C is in SECONDARY status
4. //wait for more than 10 minutes.
Now insert one more record in B
db.foo.insert({y:3})
rs1:PRIMARY> db.oplog.rs.find()
{ "ts" : { "t" : 1306176176000, "i" : 1 }, "h" : NumberLong(0), "op" :
"n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : { "t" : 1306176382000, "i" : 1 }, "h" :
NumberLong("3136021970911494161"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddaab7e77a574b12fbed4f7"), "x" : 1 } }
{ "ts" : { "t" : 1306176387000, "i" : 1 }, "h" :
NumberLong("-4259052380038851596"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddaab8377a574b12fbed4f8"), "x" : 2 } }
{ "ts" : { "t" : 1306175929000, "i" : 1 }, "h" :
NumberLong("-147207564444626001"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddaa9b957bfea93870c5782"), "y" : 1 } }
{ "ts" : { "t" : 1306175935000, "i" : 1 }, "h" :
NumberLong("7346136642044836720"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddaa9bf57bfea93870c5783"), "y" : 2 } }
{ "ts" : { "t" : 1306177210000, "i" : 1 }, "h" :
NumberLong("720390880350244707"), "op" : "i", "ns" : "test.foo", "o" :
{ "_id" : ObjectId("4ddaaeba57bfea93870c5784"), "y" : 3 }
// On C
rs1:SECONDARY> db.foo.find()
{ "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 }
{ "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 }
{ "_id" : ObjectId("4ddabdd50cc90e0d72223b6a"), "y" : 3 }
rs1:SECONDARY> use local
switched to db local
rs1:SECONDARY> db.oplog.rs.find()
{ "ts" : { "t" : 1306180706000, "i" : 1 }, "h" : NumberLong(0), "op" :
"n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : { "t" : 1306180747000, "i" : 1 }, "h" :
NumberLong("3136340678959693841"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8b3fa543a5e0e33f55"), "x" : 1 } }
{ "ts" : { "t" : 1306180751000, "i" : 1 }, "h" :
NumberLong("-3548970921664408588"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabc8f3fa543a5e0e33f56"), "x" : 2 } }
{ "ts" : { "t" : 1306181077000, "i" : 1 }, "h" :
NumberLong("-924333443697256058"), "op" : "i", "ns" : "test.foo",
"o" : { "_id" : ObjectId("4ddabdd50cc90e0d72223b6a"), "y" : 3 } }
rs1:SECONDARY>
You can see that C is missing the records {y:1} and {y:2} but {y:3}
which was inserted in B after a lag of about 10 minutes of it becoming
primary made to C.