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

MongoDB4.0下数组元素Int64字段增量超过Long.MAX_VALUE的实现方案

可行实现方案

方案前提

MongoDB 4.0 版本仅副本集部署支持多文档事务,若你使用单节点部署,可临时切换为单节点副本集开启事务能力,或使用无事务的逐文档原子更新方案。

方案1:副本集事务方案(推荐,满足全局事务性要求)

该方案在事务内完成全量数据更新,要么全部生效要么全部回滚,事务修改文档时会持有文档级排他锁,提交前其他读写操作都会阻塞,不会出现中间状态被读取或者其他写入干扰的问题,完全匹配需求。

执行脚本

// 替换为实际的数据库名、集合名
const DB_NAME = "your_database";
const COLL_NAME = "your_collection";
// 增量值为 Long.MAX_VALUE + 1 = 2^63
const DELTA = NumberLong("9223372036854775808");

const session = db.getMongo().startSession({readPreference: "primary"});
const coll = session.getDatabase(DB_NAME).getCollection(COLL_NAME);

try {
    // 开启事务,使用快照读保证读取一致性,多数派写保证数据持久化
    session.startTransaction({
        readConcern: {level: "snapshot"},
        writeConcern: {w: "majority"}
    });

    const cursor = coll.find({"versions.revision": {$lt: 0}}).noCursorTimeout();
    while (cursor.hasNext()) {
        const doc = cursor.next();
        // 应用层计算新的versions数组,避免数据库端运算的溢出、版本兼容问题
        const newVersions = doc.versions.map(elem => {
            if (elem.revision.lt(0)) {
                return Object.assign({}, elem, {revision: elem.revision.add(DELTA)});
            }
            return elem;
        });
        coll.updateOne({_id: doc._id}, {$set: {versions: newVersions}});
    }

    session.commitTransaction();
    print("更新成功,事务已提交");
} catch (e) {
    session.abortTransaction();
    print("更新失败,事务已回滚,错误信息:" + e);
    throw e;
} finally {
    session.endSession();
}

注意事项

  • 若集合数据量超过10万,建议分批处理,每批处理1万条数据开启一个事务,避免超过MongoDB默认60秒的事务生命周期限制。
  • 执行前建议先对集合做全量备份,在测试环境验证逻辑无误后再线上执行。

方案2:单节点逐文档原子更新方案

若无法使用事务,可使用乐观锁实现单文档原子更新,每个文档的更新是原子操作,不会出现中间状态,通过比对更新前的文档快照保证没有其他写入干扰。

执行脚本

// 替换为实际的数据库名、集合名
const DB_NAME = "your_database";
const COLL_NAME = "your_collection";
const DELTA = NumberLong("9223372036854775808");
// 每批次处理文档数,可根据实际情况调整
const BATCH_SIZE = 1000;

const coll = db.getSiblingDB(DB_NAME).getCollection(COLL_NAME);
let totalUpdated = 0;

while (true) {
    const docs = coll.find({"versions.revision": {$lt: 0}}).limit(BATCH_SIZE).toArray();
    if (docs.length === 0) break;

    docs.forEach(doc => {
        let retry = 3;
        while (retry > 0) {
            const newVersions = doc.versions.map(elem => {
                if (elem.revision.lt(0)) {
                    return Object.assign({}, elem, {revision: elem.revision.add(DELTA)});
                }
                return elem;
            });
            // 乐观锁:更新条件带上原始versions快照,匹配不到说明文档被修改,重试
            const updateRes = coll.updateOne(
                {_id: doc._id, versions: doc.versions},
                {$set: {versions: newVersions}}
            );
            if (updateRes.matchedCount === 1) {
                totalUpdated++;
                break;
            }
            retry--;
            // 重新拉取最新的文档快照
            doc = coll.findOne({_id: doc._id});
        }
        if (retry === 0) {
            throw new Error(`文档_id ${doc._id} 更新重试失败,请手动检查`);
        }
    });
}

print(`更新完成,共更新 ${totalUpdated} 个文档`);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 12:27:02