【发布时间】:2021-09-28 04:43:21
【问题描述】:
如果您运行以下代码,outside a transaction 对象将作为插入操作出现在 oplog 中,但 oplog 将没有 inside a transaction 的记录,但它们都会正确保存到集合中。
我尝试查找问题没有运气,虽然我能够得到a confirmation that in my mongodb server version, oplog will create a separate entry for each operation,虽然我没有得到4.0 样式,也没有得到4.2!
代码
const { MongoClient } = require('mongodb');
const dbName = "db-name";
const collectionName = "collection-name";
const dbUri = "mongodb+srv://<user>:<pass>@<cluster-url>/<db-name>?retryWrites=true&w=majority";
const client = await new MongoClient(dbUri, { useUnifiedTopology: true }).connect();
const db = client.db(dbName);
const collection = db.collection(collectionName);
const session = client.startSession();
const transactionOptions = {
readConcern: { level: 'snapshot' },
writeConcern: { w: 'majority' }
};
await collection.insertOne({ name: "outside a transaction" });
await session.withTransaction(async () => {
await collection.insertOne({ name: "inside a transaction" }, { session: session});
}, transactionOptions);
await session.endSession();
await client.close();
Oplog 结果
查询:db.oplog.rs.find({}).sort({$natural: -1})
实际数量:1
预期数量:2
{
"lsid":{
"id":{
"$binary":"IwdZfNnGTvGDoABb0gjxXQ==",
"$type":"4"
},
"uid":{
"$binary":"ddqot68vLpBUPnOuqFj2cdClv/dv/vF9ZVSwknYHEsE=",
"$type":"0"
}
},
"txnNumber":{
"$numberLong":"1"
},
"op":"i",
"ns":"testDb.tests",
"ui":{
"$binary":"2a1ZJWDySfGuvtgMK2G2gQ==",
"$type":"4"
},
"o":{
"_id":{
"$oid":"60f6feb12a662ec3fc985400"
},
"name":"outside a transaction"
},
"ts":{
"$timestamp":{
}
},
"t":{
"$numberLong":"73"
},
"wall":{
"$date":"2021-07-20T16:49:53.226Z"
},
"v":{
"$numberLong":"2"
},
"stmtId":0,
"prevOpTime":{
"ts":{
"$timestamp":{
}
},
"t":{
"$numberLong":"-1"
}
}
}
- Mongo 数据库版本:4.2
- Mongo 数据库设置:3 个成员副本集(托管在 Atlas 上)
- Mongo 驱动程序:尝试了 V3.6 和 V4 (both are compatible with the database version)
【问题讨论】:
-
据我了解,您是说此代码
await collection.insertOne({ name: "outside a transaction" });未按事务处理。我不熟悉node,但我相信节点行为与其他驱动程序相同。因此,您看到的行为是预期的,因为仅当您将相关会话对象传递给此操作时,该操作才被视为事务下的操作 -
@dododo 正确,
await collection.insertOne({ name: "outside a transaction" });预计将在事务/会话之外执行,问题或我的问题是,为什么 oplog 捕获outside a transaction而不是inside a transaction。 -
因为在您将会话传递给
insertOne之前它不在事务内部 -
从底部开始的第 4-6 行,确实有一个通过会话的 insertOne,
await collection.insertOne({ name: "inside a transaction" }, { session: session});基于上面的代码,oplog中应该有 2 个条目,但我只得到一个条目(未链接到会话的那个)。另外我认为您误解了我的问题,或者我的问题可能不够清楚,但问题不在于交易或它们如何工作,问题是为什么第二个insertOne存在于交易中没有出现在oplog -
是的,我的错,稍后可以再看一遍
标签: node.js mongodb transactions replicaset mongodb-oplog