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

如何在Atlas Functions中读取事务内未提交的更新?

问题根源

MongoDB多文档事务默认采用快照隔离级别(readConcern: "snapshot"),事务启动后,所有读操作都会基于事务开始时的数据快照执行。哪怕你在事务内完成了更新操作,后续的读操作依然只会看到事务启动时的旧数据,无法读取到本次事务内的修改结果。

解决方案

要在事务内读取到自身的更新,需要在读取操作中显式指定readConcern: { level: "local" },同时确保读操作绑定同一个事务session。

修改后的代码
exports = async function({ query, headers, body}, response) {
  const collection = context.services.get("mongodb-atlas").db("zakhar").collection("w");
  
  // clean up and insert init data
  await collection.deleteMany({});
  await collection.insertOne({"name": 1, "category": "toy"});
  await collection.insertOne({"name": 2, "category": "toy"});
  await collection.insertOne({"name": 3, "category": "game"});
  await collection.insertOne({"name": 4, "category": "game"});
  
  
  const session = context.services.get("mongodb-atlas").startSession();

  const transactionOptions = {
    readPreference: "primary",
    readConcern: { level: "local" },
    writeConcern: { w: "majority" }
  };
    
  try {
    await session.withTransaction(async () => {
      await updateStatus(session);

    }, transactionOptions);
    return 'ok';
  } catch (err) {
    await session.abortTransaction();
    throw err;
  } finally {
    await session.endSession();
  }
};

async function updateStatus(session){
  const collection = context.services.get("mongodb-atlas").db("zakhar").collection("w");

  const countBeforeUpdate = await collection.find(
    {"category": "toy"}, 
    { readConcern: { level: "local" } }, 
    { session }
  ).toArray();
  console.log("countBeforeUpdate: " + countBeforeUpdate.length);

  const query = {"name": 1};
  const update = {"$set": {"category": "game"}};
  await collection.updateOne(query, update, { session })
      .then(result => {
        const { matchedCount, modifiedCount } = result;
        console.log("matchedCount: " + matchedCount);
        console.log("modifiedCount: " + modifiedCount);
      });
      
  const countAfterUpdate = await collection.find(
    {"category": "toy"}, 
    { readConcern: { level: "local" } }, 
    { session }
  ).toArray();
  console.log("countAfterUpdate: " + countAfterUpdate.length);
}
说明
  • readConcern: "local" 允许读取到同一个事务内已完成的写操作结果,打破了快照隔离的限制,适用于需要在事务内验证修改结果的场景。
  • 事务级别的readConcern设置是默认值,若要覆盖单个读操作的级别,必须在对应读操作上显式声明。

修改后执行,countAfterUpdate会输出1,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 02:30:59