07. MongoDB 事务 ACID 支持

MongoDB 多文档事务: 开启事务、ACID 保证、隔离级别、会话管理与性能考量

MongoDB 从 4.0 开始支持 replica set 级别的多文档事务,4.2 扩展到分片集群事务。虽然 MongoDB 的事务不如关系型数据库成熟,但在需要强一致性的场景下非常有用。

1. ACID 保证

ACIDMongoDB 支持说明
Atomicity事务内所有操作同时成功或同时回滚
Consistency遵守文档验证规则和索引约束
Isolation✅ Snapshot快照隔离(Repeatable Read 级别)
Durability✅(可配置)journal 持久化

2. 事务基础用法

2.1 Mongo Shell

const session = db.getMongo().startSession();
session.startTransaction({
    readConcern: { level: "snapshot" },
    writeConcern: { w: "majority" }
});

try {
    const orders = session.getDatabase("shop").orders;
    const inventory = session.getDatabase("shop").inventory;

    // 扣减库存
    inventory.updateOne(
        { sku: "SKU001" },
        { $inc: { qty: -2 } },
        { session }
    );

    // 创建订单
    orders.insertOne({
        userId: "u123",
        items: [{ sku: "SKU001", qty: 2 }],
        status: "paid",
        createdAt: new Date()
    }, { session });

    session.commitTransaction();
} catch (error) {
    session.abortTransaction();
    throw error;
} finally {
    session.endSession();
}

2.2 驱动程序(Java)

MongoClient client = MongoClients.create("mongodb://localhost:27017");
ClientSession session = client.startSession();

TransactionOptions txnOptions = TransactionOptions.builder()
    .readConcern(ReadConcern.SNAPSHOT)
    .writeConcern(WriteConcern.MAJORITY)
    .readPreference(ReadPreference.primary())
    .build();

TransactionBody<String> txnBody = () -> {
    MongoDatabase db = client.getDatabase("shop");
    db.getCollection("inventory").updateOne(
        session, Filters.eq("sku", "SKU001"),
        Updates.inc("qty", -2)
    );
    db.getCollection("orders").insertOne(session,
        new Document("userId", "u123")
            .append("status", "paid")
            .append("createdAt", new Date())
    );
    return "Order created successfully";
};

try {
    String result = session.withTransaction(txnBody, txnOptions);
    System.out.println(result);
} catch (RuntimeException e) {
    // 事务自动回滚
    throw e;
} finally {
    session.close();
}

3. 事务限制

限制说明
事务超时默认 60 秒(maxTransactionLockRequestTimeoutMillis)
文档修改事务内无法创建/删除集合和索引
操作数量无硬性限制,但受 oplog 大小限制
分片事务涉及多个分片时性能下降明显
会话每个事务必须绑定一个会话

4. 性能影响

单文档写入:    50,000+ ops/s
多文档事务:     5,000-10,000 ops/s  (事务开销约 5-10x)

事务延迟来源:
  - 获取快照(Snapshot)
  - 两阶段提交协调(分片事务)
  - oplog 同步

最佳实践:能用单文档原子操作(update + $inc 等)就不用事务。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「mongodb」更多文章

  1. 11. MongoDB 安全认证与备份恢复
  2. 10. MongoDB 性能调优与运维监控
  3. 09. Spring Data MongoDB 实战