MongoDB / Transaction

Transaction

Transaction нь хэд хэдэн үйлдлийг нэгэн зэрэг гүйцэтгэж, бүгд амжилттай болох эсвэл бүгд цуцлагдах баталгаа өгдөг. Банкны шилжүүлэг, захиалга баталгаажуулах зэрэг алдаа гарч болохгүй нөхцөлд зайлшгүй шаардлагатай.

ACID

Transaction-ийн 4 үндсэн шинж чанар:

| Шинж | Тайлбар | | --------------- | ----------------------------------------------------------------------- | | Atomicity | Бүгд хийгддэг эсвэл бүгд болихгүй — хагас дуусаагүй байдал байхгүй | | Consistency | Үйлдлийн өмнө болон дараа өгөгдөл зөв төлөвт байна | | Isolation | Нэг transaction нь нөгөө transaction-ийн дуусаагүй өөрчлөлтийг харахгүй | | Durability | Амжилттай болсон transaction-ийн өгөгдөл алдагдахгүй |

Replica set шаардлага

MongoDB transaction нь replica set (буюу Atlas) дээр л ажилладаг. Локал standalone MongoDB-д transaction дэмжигдэхгүй.

MongoDB Atlas-д replica set анхдагчаар идэвхтэй байдаг тул Atlas ашиглаж байгаа бол ямар ч тохиргоо хэрэггүй.

Session үүсгэх

Transaction нь session дотор явагддаг:

javascript
// Session үүсгэх
const session = client.startSession();

withTransaction() — transaction ажиллуулах

withTransaction() helper нь commit ба rollback-ийг автоматаар удирддаг — хамгийн хялбар арга:

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

async function transferMoney(fromId, toId, amount) {
  const session = client.startSession();

  try {
    await session.withTransaction(async () => {
      const accounts = client.db("bank").collection("accounts");

      // Мөнгө хасах
      await accounts.updateOne(
        { _id: fromId, balance: { $gte: amount } },
        { $inc: { balance: -amount } },
        { session },
      );

      // Мөнгө нэмэх
      await accounts.updateOne(
        { _id: toId },
        { $inc: { balance: amount } },
        { session },
      );
    });

    console.log("Шилжүүлэг амжилттай боллоо");
  } catch (error) {
    console.error("Шилжүүлэг амжилтгүй болж, буцаагдлаа:", error);
  } finally {
    await session.endSession();
  }
}

Дотор алдаа гарвал withTransaction() автоматаар rollback хийнэ — өөрөөр хэлбэл мөнгийг хасчихаад нэмэхдээ алдаа гарсан ч баланс хэвийн төлөвт буцна.

Гараар commit/abort хийх

withTransaction() ашиглахгүй бол commitTransaction ба abortTransaction-ийг гараар дуудна:

javascript
const session = client.startSession();
session.startTransaction();

try {
  const orders = client.db("shop").collection("orders");
  const products = client.db("shop").collection("products");

  // Захиалга үүсгэх
  await orders.insertOne(
    { userId: "u1", productId: "p1", amount: 50000 },
    { session },
  );

  // Нөөц багасгах
  await products.updateOne({ _id: "p1" }, { $inc: { stock: -1 } }, { session });

  // Бүгд амжилттай — commit
  await session.commitTransaction();
  console.log("Захиалга баталгаажлаа");
} catch (error) {
  // Алдаа гарвал — rollback
  await session.abortTransaction();
  console.error("Захиалга цуцлагдлаа:", error);
} finally {
  await session.endSession();
}

Transaction ашиглах хэзээ?

Transaction нь overhead нэмдэг тул бүх үйлдэлд хэрэглэх шаардлагагүй:

Transaction шаардлагатай:

  • Мөнгөн шилжүүлэг (баланс хасах + нэмэх)
  • Захиалга + нөөц нэгэн зэрэг өөрчлөх
  • Олон collection-д атомик бичлэг хийх

Transaction хэрэггүй:

  • Нэг document-д бичих — MongoDB нэг document-ийн бичлэг атомик
  • Унших үйлдлүүд
  • Бие даасан үйлдлүүд
javascript
// Transaction хэрэггүй — нэг document атомик
db.users.updateOne(
  { _id: userId },
  {
    $inc: { xp: 10 },
    $addToSet: { completedLessons: "mongodb-19" },
    $set: { lastActive: new Date() },
  },
);

Дараагийн хичээлд:

MongoDB Atlas-ийн cloud үйлчилгээг хэрхэн ашиглах, холбогдох талаар үзнэ.