MST

星途 面试题库

面试题:MongoDB事务的基本使用及原理

请阐述MongoDB中事务的基本使用场景及操作步骤,例如如何开启、提交和回滚一个事务。同时简要说明其内部实现原理,包括如何保证数据一致性。
19.3万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

基本使用场景

  1. 多文档操作一致性:当需要对多个文档进行原子性操作时,比如在一个电商系统中,同时更新订单文档和库存文档,确保订单创建成功时库存相应减少,若其中一个操作失败,整个操作回滚,保证数据一致性。
  2. 跨集合操作:在复杂业务场景下,需要对不同集合的文档进行关联操作并保证一致性,如用户注册时,同时在“users”集合插入用户信息,在“profiles”集合初始化用户配置信息。

操作步骤

  1. 开启事务: 在 MongoDB 4.0 及以上版本,使用 startTransaction 方法开启事务。示例代码(以 Node.js 驱动为例):
const { MongoClient } = require('mongodb');
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

async function run() {
    try {
        await client.connect();
        const session = client.startSession();
        session.startTransaction();
        // 后续事务操作代码
    } finally {
        await client.close();
    }
}
run().catch(console.dir);
  1. 提交事务: 完成所有事务操作后,调用 commitTransaction 方法提交事务。示例:
async function run() {
    try {
        await client.connect();
        const session = client.startSession();
        session.startTransaction();
        const db = client.db('test');
        const collection = db.collection('documents');
        await collection.insertOne({ data: 'test' }, { session });
        await session.commitTransaction();
    } finally {
        await client.close();
    }
}
run().catch(console.dir);
  1. 回滚事务: 在事务执行过程中,如果出现错误,调用 abortTransaction 方法回滚事务。示例:
async function run() {
    try {
        await client.connect();
        const session = client.startSession();
        session.startTransaction();
        const db = client.db('test');
        const collection = db.collection('documents');
        await collection.insertOne({ data: 'test' }, { session });
        throw new Error('模拟错误');
        await session.commitTransaction();
    } catch (e) {
        const session = client.startSession();
        await session.abortTransaction();
    } finally {
        await client.close();
    }
}
run().catch(console.dir);

内部实现原理

  1. 两阶段提交(2PC)
    • 准备阶段:MongoDB 协调者节点(通常是主节点)向所有参与事务的节点发送准备消息,每个节点执行事务操作,但不提交更改,而是将更改记录在日志中,并向协调者返回准备成功或失败的响应。
    • 提交阶段:如果所有节点都准备成功,协调者向所有节点发送提交消息,节点将事务更改正式提交到数据库;如果有任何一个节点准备失败,协调者向所有节点发送回滚消息,节点回滚事务更改。
  2. 保证数据一致性
    • 写前日志(WAL):在事务操作过程中,所有更改先写入 WAL,确保即使系统崩溃,数据也能恢复到事务执行前的状态。
    • 多数写确认:对于复制集,事务提交需要多数节点确认写操作,保证数据在多个副本间的一致性。如果部分节点故障,只要多数节点可用,事务仍能正确提交或回滚,防止数据分裂。