0Pricing
MongoDB Academy · 강의

세션 및 다중 문서 트랜잭션 시작하기

학습자는 ClientSession을 열고 startTransaction() 내부에서 여러 작업을 실행한 다음 트랜잭션을 커밋하거나 중단합니다.

세션 및 다중 문서 트랜잭션 시작하기은(는) CoddyKit의 무료 MongoDB Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 MongoDB Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Sessions Are the Foundation

MongoDB multi-document transactions require a session. A session is a server-side context that tracks your causally consistent reads and transaction state. You create a session from the MongoClient, pass it to every operation inside the transaction, and then end the session when you are done. Forgetting to pass the session object means operations run outside the transaction and are not rolled back on abort.

Creating a Session With startSession()

Call client.startSession() to obtain a ClientSession object. This does not start a transaction yet—it only establishes the server-side context. Sessions can optionally be configured for causal consistency so that reads within the session always reflect all prior writes in the same session, even on secondaries. Always end the session in a finally block to release server resources.

const { MongoClient } = require('mongodb');
const client = new MongoClient(process.env.MONGODB_URI);

async function run() {
  const session = client.startSession();
  try {
    // ... use session here
  } finally {
    await session.endSession();
    await client.close();
  }
}

Starting a Transaction

Call session.startTransaction() with optional transaction options to begin a multi-document transaction. Common options include readConcern (typically 'snapshot' for full isolation) and writeConcern (typically { w: 'majority' } for durable commits). Once started, all operations that pass this session are part of the transaction and will be rolled back if the transaction aborts.

session.startTransaction({
  readConcern: { level: 'snapshot' },
  writeConcern: { w: 'majority' }
});

Passing the Session to Operations

Every operation you want to include in the transaction must receive the session object as an option. If you forget to pass the session to an operation, it runs outside the transaction with its own independent write that will not be rolled back on abort. This is a common source of bugs in transaction code—always double-check that every insert, update, and delete inside the try block receives the session.

const db = client.db('bank');
const accounts = db.collection('accounts');

// Both operations must receive { session } to be part of the transaction
await accounts.updateOne(
  { _id: fromAccountId },
  { $inc: { balance: -transferAmount } },
  { session }  // <-- REQUIRED
);

await accounts.updateOne(
  { _id: toAccountId },
  { $inc: { balance: transferAmount } },
  { session }  // <-- REQUIRED
);

Committing With commitTransaction()

After all operations complete successfully, call session.commitTransaction() to atomically apply all changes to the database. Until commit is called, none of the transaction's writes are visible to other operations. On commit, MongoDB applies all writes and acknowledges according to the write concern. A successful commit means all operations in the transaction are durably saved.

session.startTransaction();
try {
  await accounts.updateOne({ _id: fromId }, { $inc: { balance: -100 } }, { session });
  await accounts.updateOne({ _id: toId }, { $inc: { balance: 100 } }, { session });
  await session.commitTransaction();
  console.log('Transfer committed successfully');
} catch (error) {
  await session.abortTransaction();
  throw error;
}

Aborting With abortTransaction()

If any operation in the transaction fails or if your application logic determines the transaction should not proceed, call session.abortTransaction(). This rolls back all writes made in the transaction as if none of them happened. MongoDB guarantees that no partial state will be left—other readers will never see any of the aborted transaction's writes.

session.startTransaction();
try {
  const inventory = await db.collection('inventory').findOne({ _id: itemId }, { session });
  
  if (inventory.stock < requestedQty) {
    // Business logic: not enough stock — abort
    await session.abortTransaction();
    return { success: false, reason: 'Insufficient stock' };
  }
  
  await db.collection('inventory').updateOne(
    { _id: itemId }, { $inc: { stock: -requestedQty } }, { session }
  );
  await db.collection('orders').insertOne({ itemId, qty: requestedQty, status: 'confirmed' }, { session });
  await session.commitTransaction();
  return { success: true };
} catch (error) {
  await session.abortTransaction();
  throw error;
}

The withTransaction() Helper

The Node.js driver provides a convenient session.withTransaction(fn) helper that automatically handles starting, committing, and aborting the transaction, including automatic retries for transient errors. The callback function receives the session and should contain all your transaction operations. Using withTransaction is recommended over manual start/commit/abort because it correctly handles the retry logic MongoDB requires.

const session = client.startSession();
try {
  await session.withTransaction(async () => {
    await accounts.updateOne({ _id: fromId }, { $inc: { balance: -100 } }, { session });
    await accounts.updateOne({ _id: toId }, { $inc: { balance: 100 } }, { session });
    // withTransaction auto-commits on success, auto-aborts on error, and retries transient errors
  }, {
    readConcern: { level: 'snapshot' },
    writeConcern: { w: 'majority' }
  });
} finally {
  await session.endSession();
}

Transaction Scope and Collections

A MongoDB transaction can span multiple collections and databases within the same cluster (MongoDB 4.2+ for sharded clusters). You can read from one collection, update another, and insert into a third—all within a single atomic transaction. The only restriction is that you cannot create new collections or indexes inside a multi-document transaction; those DDL operations must happen outside transactions.

await session.withTransaction(async () => {
  const db = client.db('ecommerce');
  
  // Span multiple collections in one transaction
  await db.collection('inventory').updateOne(
    { productId: 'P1' }, { $inc: { stock: -qty } }, { session }
  );
  await db.collection('orders').insertOne(
    { productId: 'P1', qty, status: 'new', createdAt: new Date() }, { session }
  );
  await db.collection('customers').updateOne(
    { _id: customerId }, { $push: { orderHistory: orderId } }, { session }
  );
});

Transactions Require Replica Sets

Multi-document transactions require a replica set or sharded cluster—they do not work on a standalone MongoDB instance. On a standalone, the transaction API exists but calling startTransaction() throws an error. This means your local development setup should use a local replica set (e.g., via mongod --replSet rs0 or via Atlas free tier) if your application code uses transactions.

// Starting a local replica set for development:
// 1. Start mongod with replica set name
// mongod --replSet rs0 --port 27017 --dbpath /data/db

// 2. In mongosh, initiate the replica set:
// rs.initiate()

// Now transactions will work on localhost

Transaction Timeout and Limits

MongoDB enforces a 60-second maximum transaction lifetime by default (configurable via transactionLifetimeLimitSeconds). Transactions that run longer are automatically aborted. Additionally, transactions are capped to 16 MB of oplog space for write operations. Long-running transactions also hold locks and can degrade performance for concurrent operations, so keep transactions short and focused.

Full Transfer Example With Validation

Putting it all together: a complete, production-ready bank transfer function using withTransaction. It validates sufficient balance inside the transaction (ensuring no other writer could have drained the account between the check and the debit) and records an audit entry atomically. This pattern demonstrates all key transaction concepts.

async function transferFunds(client, fromId, toId, amount) {
  const session = client.startSession();
  try {
    await session.withTransaction(async () => {
      const accounts = client.db('bank').collection('accounts');
      const from = await accounts.findOne({ _id: fromId }, { session });
      
      if (!from || from.balance < amount) {
        throw new Error('Insufficient funds');
      }
      
      await accounts.updateOne({ _id: fromId }, { $inc: { balance: -amount } }, { session });
      await accounts.updateOne({ _id: toId }, { $inc: { balance: amount } }, { session });
      await client.db('bank').collection('auditLog').insertOne(
        { from: fromId, to: toId, amount, date: new Date(), type: 'transfer' }, { session }
      );
    });
    return { success: true };
  } finally {
    await session.endSession();
  }
}

Quick Check

Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.

Lesson Recap

In this lesson you learned: transactions require a ClientSession created with client.startSession(), every operation in the transaction must receive { session } to be included, and withTransaction() is the recommended helper because it handles retry logic and cleanup automatically. Next up we explore error handling and retry logic for transient transaction failures.

자주 묻는 질문

“세션 및 다중 문서 트랜잭션 시작하기” 강의는 무료인가요?

네 — “세션 및 다중 문서 트랜잭션 시작하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 MongoDB Academy 강의 전체를 잠금 해제할 수 있습니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“세션 및 다중 문서 트랜잭션 시작하기”에서 뭘 배우나요?

학습자는 ClientSession을 열고 startTransaction() 내부에서 여러 작업을 실행한 다음 트랜잭션을 커밋하거나 중단합니다. 브라우저에서 직접 실행하는 실습 코드로 MongoDB Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

MongoDB Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 MongoDB Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“세션 및 다중 문서 트랜잭션 시작하기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 MongoDB Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 MongoDB Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 분산 문서 저장소의 ACID 보장
  2. 세션 및 다중 문서 트랜잭션 시작하기
  3. 오류 처리 및 재시도 로직
  4. 트랜잭션 성능 고려 사항
← MongoDB Academy(으)로 돌아가기