Giao dịch MongoDB

Giao dịch mới trong MongoDB 4. 0 và Mongoose 5. 2. 0. Giao dịch cho phép bạn thực hiện nhiều thao tác một cách độc lập và có khả năng hoàn tác tất cả các thao tác nếu một trong số chúng không thành công. Hướng dẫn này sẽ giúp bạn bắt đầu sử dụng các giao dịch với Mongoose

Nếu bạn chưa có, hãy nhập cầy mangut

import mongoose from 'mongoose';

Để tạo giao dịch, trước tiên bạn cần tạo phiên sử dụng hoặc hoặc

Trong thực tế, bạn nên sử dụng hàm Connection#transaction() của Mongoose hoặc của Mongoose để thực hiện giao dịch. Trình trợ giúp session.withTransaction() xử lý

  • Tạo một giao dịch
  • Cam kết giao dịch nếu thành công
  • Hủy bỏ giao dịch nếu hoạt động của bạn ném
  • Thử lại trong trường hợp xảy ra lỗi giao dịch tạm thời

Để biết thêm thông tin về hàm ClientSession#withTransaction(), vui lòng xem

Chức năng Connection#transaction() của Mongoose là một trình bao bọc xung quanh

[require:transactions.*can save document after aborted transaction]
1 tích hợp theo dõi thay đổi của Mongoose với các giao dịch. Ví dụ: giả sử bạn
[require:transactions.*can save document after aborted transaction]
2 một tài liệu trong một giao dịch mà sau đó không thành công. Những thay đổi trong tài liệu đó không được duy trì đối với MongoDB. Hàm Connection#transaction() thông báo theo dõi thay đổi Mongoose rằng
[require:transactions.*can save document after aborted transaction]
2 đã được khôi phục và đánh dấu tất cả các trường đã được thay đổi trong giao dịch là đã sửa đổi

[require:transactions.*can save document after aborted transaction]

Nếu bạn nhận tài liệu Mongoose từ hoặc sử dụng phiên, tài liệu sẽ giữ tham chiếu đến phiên và sử dụng phiên đó cho

Để nhận/đặt phiên được liên kết với một tài liệu nhất định, hãy sử dụng

Hàm

[require:transactions.*can save document after aborted transaction]
9 cũng hỗ trợ các giao dịch. Các tập hợp Mongoose có một tập hợp. Dưới đây là một ví dụ về việc thực hiện một tập hợp trong một giao dịch

const Event = db.model('Event', new Schema({ createdAt: Date }), 'Event');

let session = null;
return Event.createCollection().
  then(() => db.startSession()).
  then(_session => {
    session = _session;
    session.startTransaction();
    return Event.insertMany([
      { createdAt: new Date('2018-06-01') },
      { createdAt: new Date('2018-06-02') },
      { createdAt: new Date('2017-06-01') },
      { createdAt: new Date('2017-05-31') }
    ], { session: session });
  }).
  then(() => Event.aggregate([
    {
      $group: {
        _id: {
          month: { $month: '$createdAt' },
          year: { $year: '$createdAt' }
        },
        count: { $sum: 1 }
      }
    },
    { $sort: { count: -1, '_id.year': -1, '_id.month': -1 } }
  ]).session(session)).
  then(res => assert.deepEqual(res, [
    { _id: { month: 6, year: 2018 }, count: 2 },
    { _id: { month: 6, year: 2017 }, count: 1 },
    { _id: { month: 5, year: 2017 }, count: 1 }
  ])).
  then(() => session.commitTransaction()).
  then(() => session.endSession());

Người dùng nâng cao muốn kiểm soát chi tiết hơn khi họ thực hiện hoặc hủy bỏ giao dịch có thể sử dụng

const Event = db.model('Event', new Schema({ createdAt: Date }), 'Event');

let session = null;
return Event.createCollection().
  then(() => db.startSession()).
  then(_session => {
    session = _session;
    session.startTransaction();
    return Event.insertMany([
      { createdAt: new Date('2018-06-01') },
      { createdAt: new Date('2018-06-02') },
      { createdAt: new Date('2017-06-01') },
      { createdAt: new Date('2017-05-31') }
    ], { session: session });
  }).
  then(() => Event.aggregate([
    {
      $group: {
        _id: {
          month: { $month: '$createdAt' },
          year: { $year: '$createdAt' }
        },
        count: { $sum: 1 }
      }
    },
    { $sort: { count: -1, '_id.year': -1, '_id.month': -1 } }
  ]).session(session)).
  then(res => assert.deepEqual(res, [
    { _id: { month: 6, year: 2018 }, count: 2 },
    { _id: { month: 6, year: 2017 }, count: 1 },
    { _id: { month: 5, year: 2017 }, count: 1 }
  ])).
  then(() => session.commitTransaction()).
  then(() => session.endSession());
2 để bắt đầu giao dịch

Tôi tin rằng những lập trình viên đã sử dụng cơ sở dữ liệu quan hệ chính thống không quá xa lạ với Giao dịch. Nhiều hoạt động dữ liệu có thể va vào nhau và khi xảy ra lỗi trong bất kỳ hàm thực thi nào thì giao dịch sẽ bị hủy bỏ và dữ liệu sẽ được khôi phục, đảm bảo tính thống nhất của dữ liệu khi sửa đổi dữ liệu trong


Những trường hợp thực tế phải sử dụng Giao dịch

Thực tế có nhiều trường hợp xảy ra và được sử dụng Giao dịch nhiều nhất. Cụ thể là hai trường hợp mà tôi sẽ đề cập đến đó là việc chuyển tiền trong Ngân hàng và trường hợp thứ 2 đó là đặt hàng trực tuyến như tiki, shoppee, lazada.  


Trường hợp 1.  


Hiện tại có hai người dùng, người dùng A (anonystick) có số dư là 50 đồng , người dùng B có số dư là . Giả sử rằng kịch bản chuyển tiền rất an toàn, mạng cũng thông suốt, không có hacker đánh chặn và không có tai nạn gì về code và lần này chuyển khoản thành công, lúc này người dùng A có số dư là 40 đồng và người . Tuyệt vời, giá như cuộc sống diễn ra luôn như vậy nhưng. 10 đồng và người dùng A chuyển 10 đồng sang B. Giả sử rằng kịch bản chuyển tiền rất an toàn, mạng cũng thông suốt, không có hacker đánh chặn và không có tai nạn gì về code và lần này chuyển khoản thành công, lúc này người dùng A có số dư là 40 đồng và người dùng B có số dư là 20. Tuyệt vời, giá như cuộc sống diễn ra luôn là như vậy nhưng... 


A cảm thấy rất an toàn, sau đó tiếp tục chuyển cho B. A.quên số dư của mình hiện tại là bao nhiêu và chuyển tiếp 50 đồng cho B, nhưng giả sử đã xảy ra lỗi. Khi giao dịch xảy ra thì cơ sở dữ liệu hoạt động như sau.


1. Số dư của tài khoản A là -50

2. Tài khoản B tăng thêm 50.  


Khi số dư của tài khoản A thiếu hoặc xảy ra lỗi mạng sau khi hoạt động của tài khoản A đã bị trừ nhưng đã xảy ra lỗi thì ngay tại đây Giao dịch xảy ra thì B không có cơ hội để nhận số tiền trên. Trong trường hợp của một giao dịch (Transaction), ngay cả khi xảy ra lỗi sau khi vận hành số tiền của tài khoản A, giao dịch sẽ khôi phục toàn bộ quá trình chuyển về trước khi sửa đổi.  


Có nghĩa là sau khi trừ 50 thì A còn -10 những cái sẽ được phục hồi sau khi xảy ra lỗi do tính năng giao dịch của cơ sở dữ liệu


Giao dịch là gì?

Qua ví dụ thực tế thì các bạn cũng hiểu ý nghĩa về Giao dịch là gì rồi đúng không?


Giao dịch được thực hiện bởi phiên bản khách hàng được kết nối bởi Cơ sở dữ liệu (MongoDB, Mysql. ). Quá trình thực hiện Giao dịch đại khái là thiết lập một phiên bản, bắt đầu giao dịch thông qua phiên bắt đầu Giao dịch, nếu một chuỗi Giao dịch hoàn thành thì commitTransaction hoàn thành thao tác Giao dịch và kết thúc phiên Giao dịch hiện tại; . Nói ít mà hiểu nhiều.  


phiên = khách hàng. startSession();

phiên họp. startTransaction();

phiên họp. cam kếtTransaction();

phiên họp. hủy bỏ Giao dịch();

phiên họp. Phiên kết thúc();


Thực hiện giao dịch với mongodb 4. 0

Đầu tiên bạn phải cài đặt mongodb và cài đặt MongoDB.  

Ghi chú. Giao dịch  chỉ áp dụng cho bộ bản sao, vì trước tiên bạn phải xây dựng bộ bản sao trong mongodb

Thiết lập replica set trong mongodb

________số 8_______

setup replica set mongoDB

demo transaction mongodb

Tạo giao dịch thử nghiệm dự án với nodejs

Cứ sao chép về làm theo thôi

AnonyStick$ 
AnonyStick$ mkdir mongodb4Transaction
AnonyStick$ cd mongodb4Transaction/
AnonyStick$ npm init
AnonyStick$ npm i mongodb -S
AnonyStick$ vi app.js

ứng dụng tệp. js

(async function()  {

  // Connect
  const { MongoClient } = require('mongodb');
  const uri = 'mongodb://localhost:1301/dbfour';
  const client = await MongoClient.connect(uri, { useNewUrlParser: true });

  const db = client.db();
  await db.dropDatabase();
  console.log('(1) Xoá hết database nếu tồn tại \n')

  // Tạ dữ liệu cho hai tài khoản
  await db.collection('Account').insertMany([
    { name: 'A', balance: 50 },
    { name: 'B', balance: 10 }
  ]);
  console.log('(2) Thực hiện insertMany,  Tài khoản Anonystick có 50 đồng, Tài khoản B  có 10 đồng\n')


  await transfer('A', 'B', 10); // lần 1
  console.log('(3) Sau đó Anonystick chuyển tiền cho B 10 đồng\n')

  try {
    // test chuyển tiền sô dư không đủ
    console.log('(4) Anonystick lại chuyển tiền cho B 50\n')
    await transfer('A', 'B', 50);

  } catch (error) {
    //error.message; // "Không đủ tiền: 40"
    console.log(error.message)
    console.log('\n(5) Thông báo cho tài khoản anonystick - Số dư không đủ nên thao tác chuyển này không thành công')
  }

  // Lệnh chuyển tiền
  async function transfer(from, to, amount) {
    const session = client.startSession();
    session.startTransaction();
    try {
      const opts = { session, returnOriginal: false };
      const A = await db.collection('Account').
        findOneAndUpdate({ name: from }, { $inc: { balance: -amount } }, opts).
        then(res => res.value);
        console.log('A>>>A', A)
      if (A.balance < 0) {
        // Nếu số dư của Anonystick không đủ, việc chuyển tiền không thành công và giao dịch bị hủy bỏ
        // `session.abortTransaction()` có nhiềm vụ Sẽ hoàn tác thao tác `findOneAndUpdate () 'ở trên

        //select lại lần nữa?
        console.log(await db.collection('Account').findOne({name: from}))
        throw new Error('Không đủ tiền: ' + (A.balance + amount));
      }

      const B = await db.collection('Account').
        findOneAndUpdate({ name: to }, { $inc: { balance: amount } }, opts).
        then(res => res.value);

      await session.commitTransaction();
      session.endSession();
      return { from: A, to: B };
    } catch (error) {
      // Nếu xảy ra lỗi, hãy hủy bỏ tất cả các giao dịch và quay trở lại trước khi sửa đổi
      console.log('Loi ne');
      await session.abortTransaction();
      session.endSession();
      throw error; // catch error
    }
  }

})()

View results

node app.js

transaction la gi?

Như vậy bài viết vừa rồi giúp bạn hiểu được "Giao dịch là gì?" . Nếu các bạn cần code thì liên hệ tại gmail nhé. Cảm ơn vì đã đọc

Giao dịch trong MongoDB là gì?

Giao dịch và hoạt động . 2, mảnh Distributed transactions can be used across multiple operations, collections, databases, documents, and, starting in MongoDB 4.2, shards . Đối với giao dịch. Bạn có thể chỉ định thao tác đọc/ghi (CRUD) trên các bộ sưu tập hiện có. Để biết danh sách các hoạt động CRUD, hãy xem Hoạt động CRUD.

@transactional có hoạt động với MongoDB không?

MongoDB luôn cung cấp đảm bảo giao dịch cho các hoạt động trên một tài liệu . nguyên tử. Các hoạt động tài liệu đơn lẻ luôn là nguyên tử trong MongoDB. Các thao tác này có thể ghi vào một hoặc nhiều trường, bao gồm các tài liệu con, các phần tử trong một mảng và thậm chí cả các mảng lồng nhau.

MongoDB triển khai các giao dịch như thế nào?

Các giao dịch MongoDB tồn tại trong các phiên. Bạn tạo phiên sử dụng startSession() và theo dõi phiên. startTransaction() để sắp xếp các hoạt động giao dịch của bạn được cam kết . Để cố ý khôi phục những thay đổi đó, bạn có thể sử dụng phiên.

Tại sao MongoDB không phải là giao dịch?

Không có giao dịch là một sự đánh đổi để cho phép MongoDB có thể mở rộng . Mục đích của giao dịch là đảm bảo rằng toàn bộ cơ sở dữ liệu luôn nhất quán trong khi nhiều hoạt động diễn ra. Nhưng trái ngược với hầu hết các cơ sở dữ liệu quan hệ, MongoDB không được thiết kế để chạy trên một máy chủ duy nhất.