You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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();

关键修改说明

  1. 添加事务提交逻辑:在第一个事务的insert操作后,必须调用await session.commitTransaction(),确保事务内的写入操作被持久化到副本集的多数节点(符合你设置的writeConcern)。
  2. 增加异常处理:通过try/catch捕获事务执行中的错误,调用abortTransaction()回滚事务,避免脏数据或资源泄漏。
  3. 修正readConcern配置:原代码中readConcern里的w参数是无效的,readConcern的配置项只有level,w属于writeConcern的配置,已修正。

额外说明

  • 当你不使用事务直接调用insertOne()时,MongoDB会自动将操作作为单文档事务提交,所以数据能正常读取,这和事务内的操作逻辑本质是一致的——只是显式事务需要你手动完成提交步骤。
  • 你的副本集配置和mongodb包版本没有问题,核心错误就是遗漏了事务提交步骤。

内容的提问来源于stack exchange,提问作者pubkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:26:19