使用MongoDB事务插入数据后无法在新事务中读取的问题
MongoDB副本集事务插入后新事务无法读取的问题解决
问题核心原因
你遇到的问题根本原因是第一个事务没有提交。MongoDB的事务不会自动提交,启动事务后必须显式调用session.commitTransaction()才能将事务内的操作持久化到数据库。你的代码中只调用了session.endSession(),这会导致事务被隐式中止,插入的文档并没有真正写入数据库,所以后续新事务自然读不到数据。
修正后的代码
const { MongoClient } = require('mongodb'); const assert = require('assert'); async function run() { const dbName = 'mydb' + new Date().getTime(); const mongoClient = new MongoClient('mongodb://localhost:27017,localhost:27018,localhost:27019'); const mongoDatabase = mongoClient.db(dbName); const mongoCollection = await mongoDatabase.createCollection('mycollection'); const transactionOptions = { defaultTransactionOptions: { readConcern: { level: 'majority' }, writeConcern: { w: 3, journal: true } } }; // 插入事务:添加提交逻辑 let session = mongoClient.startSession(transactionOptions); try { session.startTransaction(); await mongoCollection.insertOne({ bar: 'foo' }, { session }); // 显式提交事务,这一步是关键 await session.commitTransaction(); } catch (err) { // 出错时回滚事务 await session.abortTransaction(); throw err; } finally { // 无论成功失败都结束会话 await session.endSession(); } // 新事务中读取数据 session = mongoClient.startSession(transactionOptions); try { session.startTransaction(); const allDocs = await mongoCollection.find({}, { session }).toArray(); console.dir(allDocs); assert.strictEqual(allDocs.length, 1); await session.commitTransaction(); } catch (err) { await session.abortTransaction(); throw err; } finally { await session.endSession(); } await mongoClient.close(); } run();
关键修改说明
- 添加事务提交逻辑:在第一个事务的insert操作后,必须调用
await session.commitTransaction(),确保事务内的写入操作被持久化到副本集的多数节点(符合你设置的writeConcern)。 - 增加异常处理:通过try/catch捕获事务执行中的错误,调用
abortTransaction()回滚事务,避免脏数据或资源泄漏。 - 修正readConcern配置:原代码中readConcern里的
w参数是无效的,readConcern的配置项只有level,w属于writeConcern的配置,已修正。
额外说明
- 当你不使用事务直接调用
insertOne()时,MongoDB会自动将操作作为单文档事务提交,所以数据能正常读取,这和事务内的操作逻辑本质是一致的——只是显式事务需要你手动完成提交步骤。 - 你的副本集配置和mongodb包版本没有问题,核心错误就是遗漏了事务提交步骤。
内容的提问来源于stack exchange,提问作者pubkey
相关产品推荐
相关产品推荐

