Chúng tôi có thể sử dụng MongoDB cho các giao dịch không?

Trong khoa học máy tính có các khái niệm ACID (Nguyên tử, Tính nhất quán, Cách ly, Độ bền), nguyên tử và tính toàn vẹn tham chiếu. Thuật ngữ nào bạn biết, phần lớn phụ thuộc vào độ tuổi của bạn. Tôi biết người cuối cùng, điều này cho bạn manh mối để hiểu tôi già

Về cơ bản tất cả các thuật ngữ này có nghĩa giống nhau. điều đó có nghĩa là máy tính sẽ thực hiện bất kỳ giao dịch nào dẫn đến một tập hợp các giao dịch không nhất quán về mặt logic

(Bài viết này là một phần của Hướng dẫn MongoDB của chúng tôi. Sử dụng menu bên phải để điều hướng. )

Tại sao nó lại quan trọng?

Hãy tưởng tượng nếu bạn có một đơn đặt hàng và hệ thống kiểm soát hàng tồn kho. Khi bạn bán hàng, nó sẽ làm giảm hàng tồn kho trong tay. Nhưng điều gì xảy ra nếu giao dịch bán hàng hoạt động sau đó cập nhật hàng tồn kho không thành công? . hàng tồn kho sẽ không khớp với doanh số bán hàng

Cách để tránh điều đó là nhóm hai giao dịch thành một giao dịch lớn hơn. Các lập trình viên cơ sở dữ liệu Oracle biết đây là câu lệnh bắt đầu và cam kết. MongoDB hỗ trợ cùng một khái niệm mà chúng tôi minh họa bên dưới

Lần truy cập hiệu suất

Mặc dù MongoDB hỗ trợ các giao dịch, nhưng nó nhấn mạnh rằng do các vấn đề về hiệu suất, tốt hơn hết là nhúng tài liệu dưới dạng mảng JSON. Nói cách khác, đặt tất cả dữ liệu cho một mục và dữ liệu liên quan của nó vào một tài liệu

Các lập trình viên của Oracle sẽ nói rằng kết quả là cơ sở dữ liệu không được chuẩn hóa. Nhưng điều đó không thành vấn đề, vì cơ sở dữ liệu dữ liệu lớn đã loại bỏ khái niệm đó, nói rằng có thể lưu trữ cùng một dữ liệu trong hai bản ghi, vì trọng tâm của chúng là tốc độ và việc sử dụng thêm dung lượng đĩa để lưu trữ thứ gì đó hai lần không thành vấn đề, vì

Nói cách khác, bạn có thể có mã zip 29607 và từ Greenville, SC trong hai bản ghi. Bạn không cần giữ một bảng mã zip như một thực thể riêng biệt, như cách bạn làm với phương pháp rdbms

Minh họa giao dịch

Bạn cần cài đặt MongoDB theo cụm để thực hiện việc này, nhưng bạn có thể giả vờ rằng bạn có một cụm chỉ có máy chủ trên máy tính xách tay của mình. Chỉ cần giả vờ rằng các bản sao đang ngoại tuyến, bằng cách không cài đặt mà chỉ cài đặt một nút. Nói cách khác, hãy làm theo các hướng dẫn mà chúng tôi đã viết, nhưng xóa phần trong /etc/mongodConfig. conf như hình bên dưới và chỉ thiết lập một máy chủ

sharding:
clusterRole: configsvr

Để sử dụng các giao dịch, bạn phải bật sao chép và tắt phân đoạn. Hỗ trợ cho cơ sở dữ liệu được phân đoạn đi kèm với MongoDB 4. 2. Dưới đây chúng tôi sử dụng 4. 0. 5

Tạo một số dữ liệu

Mở vỏ mongo và tạo các sản phẩm và bộ sưu tập bán hàng, sau đó thêm một sản phẩm vào kho. Chúng tôi thêm 100 mặt hàng của sản phẩm 123

use products
db.createCollection("products")
db.createCollection("sales")
db.products.insert({product: 123, count: 100})

Bây giờ, bán 4 mặt hàng của sản phẩm 123. Kết quả sẽ là 96 mặt hàng còn lại trong kho. Vì vậy, hãy thêm một giao dịch bán hàng và cập nhật số lượng hàng tồn kho thành 96 được hiển thị bên dưới

Either paste that code into the MongoDB shell or save it in a JavaScript text file and then run it with load(‘’).

session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
productsCollection = session.getDatabase("products").products;
salesCollection = session.getDatabase("products").sales;
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
try {
salesCollection.insertOne( { 
product: 123, 
count: 4
}
);
productsCollection.update(
{ product: 123 },
{ $set:
{
count: 96
}
}
);
} catch (error) {
session.abortTransaction();
throw error;
}
session.commitTransaction();
session.endSession();

Giải thích mã

Đầu tiên, kiểm tra đã hoạt động

db.products.findOne();
{
"_id" : ObjectId("5cb8ccb664ae78fe855e9431"),
"product" : 123,
"count" : 96
}

Các phần chính của mã là

phiên họp. startTransaction( { readConcern. { cấp độ. “ảnh chụp nhanh” }, writeConcern. {w. “đa số” } } );Bắt đầu giao dịch. phiên họp. cam kếtTransaction();

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

Cam kết giao dịch. Nó sẽ chỉ đến đây nếu các giao dịch giữa hai câu lệnh hoạt động do khối thử bắt. phiên họp. abortTransaction() Có nghĩa là không thực hiện một trong hai giao dịch. sản phẩmBộ sưu tập. cập nhật(
{ sản phẩm. 123 },
{ $set
{
đếm. 96
}
}
) Định dạng của cái này là db. thu thập. cập nhật (truy vấn tìm bản ghi, cập nhật trường nào)

Chúng tôi cập nhật sản phẩm 123 và đặt số đếm thành 96

Xử lý sự cố

Nếu bạn đang cố thực hiện điều này với cài đặt hiện tại của mình và không bật sao chép hoặc tắt phân đoạn hoặc thực hiện một số câu lệnh phi logic trong mã của mình, thì bạn sẽ gặp phải bất kỳ lỗi nào trong số này

Phiên bản MongoDB mới nhất 4. 2 giao dịch đa tài liệu được giới thiệu. Đây là một tính năng quan trọng bị thiếu trong hầu hết các cơ sở dữ liệu NoSQL (và các cơ sở dữ liệu SQL đã khoe khoang về điều đó)

Một giao dịch, có thể bao gồm một hoặc nhiều hoạt động, hoạt động như một hoạt động nguyên tử. Nếu tất cả các thao tác con thành công, giao dịch đó được coi là hoàn thành. Nếu không nó không thành công

Đây được gọi là tính nguyên tử. Đây là một khái niệm quan trọng cần hiểu để giữ cho dữ liệu của bạn nhất quán khi đọc/ghi dữ liệu đồng thời

Phạm Vi Bài Viết Và Mục Tiêu

Mục tiêu của bài viết này là cung cấp cho bạn một ví dụ thực tế trong đó dữ liệu không nhất quán xảy ra mà không có giao dịch. Sau đó, chúng tôi sẽ xây dựng một giải pháp trong Java bằng cách sử dụng Giao dịch MongoDB để ngăn chặn chúng

Làm như vậy, bạn sẽ học cách

  1. Tránh các Điều kiện cuộc đua có thể dẫn đến sự không thống nhất về dữ liệu
  2. Xây dựng các ứng dụng linh hoạt hơn bằng cách sử dụng tính năng Ghi có thể thử lại tích hợp sẵn của Mongo

Ngoài ra, tôi đã thêm một hàm bao bọc, static R withTransaction(final Function executeFn);, mà bạn có thể sử dụng để cải thiện khả năng đọc mã

Thí dụ. Cách xử lý các giao dịch đồng thời trên cùng một tài khoản ngân hàng

Giả sử bạn và người phối ngẫu của bạn chia sẻ một tài khoản ngân hàng chung. Mỗi bạn đến cây ATM cùng một lúc và bắt đầu rút tiền

t1 -> You: Press check balance. ATM shows 100 dollars
t2 -> Spouse: Press check balance. ATM shows 100 dollars
t3 -> You & Spouse: withdraw 10 dollars
t4 -> Bank: initializes P1 and P2 to handle your and your spouse's requests.
t5 -> P1 and P2 checked the balance and saw 100 dollars
t6 -> P1 and P2 subtracted 10 dollars from the balance
t7 -> P1 updated the DB with the new balance of 90
t8 -> P2 updated the DB with the new balance of 90
t1 - t8 là dòng thời gian của các sự kiện. P1 và P2 là một quy trình xử lý các yêu cầu từ các máy ATM của Ngân hàng

Trong ví dụ trên, các hoạt động không diễn ra tuần tự. Quá trình của ngân hàng P2 không đợi P1 hoàn thành nhiệm vụ của mình. Nếu ngân hàng đã đợi P1 đọc xong số dư, tính toán số dư mới và ghi số dư cập nhật trở lại DB trước khi đọc số dư mới nhất, thì ngân hàng sẽ không bị mất 10 đô la

Giải pháp cho vấn đề này là các giao dịch. Bạn có thể coi chúng tương tự như các khối Khóa, Semaphores và Đồng bộ hóa trong Java. Trong Java, nó đảm bảo rằng chỉ người giữ Khóa mới thực thi mã được bảo vệ bởi khóa

Cách thiết lập chức năng trợ giúp

Bây giờ chúng ta hãy đến phần mã hóa. Tôi sẽ cho rằng bạn đã có thiết lập MongoClient. Bạn sẽ cần

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

Một số chức năng chung cần thiết ví dụ dưới đây

getNewClientSession chỉ cần trả về một phiên cho một giao dịch. ClientSession là mã định danh cho một giao dịch cụ thể. Đây là một phần dữ liệu quan trọng mà bạn chuyển vào tất cả các hoạt động Mongo sau để nó có thể tách biệt các hoạt động

getTransactionOptions cung cấp các tùy chọn cho Giao dịch. ReadPreference.primary() cung cấp cho chúng tôi thông tin cập nhật nhất về một cụm khi chúng tôi đang đọc dữ liệu.

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

0 dẫn đến việc DB thừa nhận một cam kết sau khi nó ghi thành công vào phần lớn các máy chủ

Thay vì tạo các phiên khách hàng và các tùy chọn giao dịch ở khắp mọi nơi, thay vào đó chúng ta nên thực hiện nó trên một phương thức duy nhất và chỉ chuyển các hàm cần tính nguyên tử cho nó

static  R withTransaction(final Function executeFn) {
	final ClientSession clientSession = getNewClientSession();
	TransactionOptions txnOptions = this.getTransactionOptions();
       
	TransactionBody txnBody = new TransactionBody() {
		public R execute() {
			return executeFn.apply(clientSession);
		}
	};

	try {
		return clientSession.withTransaction(txnBody, txnOptions);
	} catch (RuntimeException e) {
		e.printStackTrace();
	} finally {
		clientSession.close();
	}
	return null;
}
Hàm chung để thực thi Hàm trong một giao dịch

Hàm trên chạy các hoạt động bên trong hàm được truyền vào, đối số

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

1, dưới dạng hoạt động nguyên tử hoặc giao dịch. Hãy triển khai chức năng rút tiền của chúng ta bằng các giao dịch

Lưu ý rằng tôi đang trở lại

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

2. Bạn chỉ có thể đưa ra một ngoại lệ mới để cho người gọi biết rằng giao dịch đã thất bại. Vì lợi ích của ví dụ này, việc trả về null có nghĩa là giao dịch thất bại

Ví dụ về tài khoản ngân hàng trong Java

public class Account {
	@BsonId
    ObjectId _id;
	int balance;
    
    .. getters and setters
}

public class AccountService {
	public Collection getAccounts() {
    	return dbClient.getCollection('account', Account.class);
    }
    
    private Account currentBalance(ClientSession session, Bson accountId) {
    	return getAccounts().findOne(session, Filters.eq('_id', accountId)).first();
    }
    
	private int currentBalance(ClientSession session, Bson accountId) {
    	Account account = getAccounts().findOne(session, Filters.eq('_id', accountId)).first();
        return account.balance;
    }
    
    private int updateBalance(ClientSession session, Bson accountId, int newBalance) {
    	Account account = getAccounts().updateOne(session, Filters.eq('_id', accountId), Updates.set('balance', newBalance)).first();
        return account.balance;
    }
    
    public Account drawCash(ClientSession session, Bson accountId, int amount){
    	int currentBalance = this.currentBalance(accountId);
        int newBalance = currentBalance - amount;
        return updateBalance(session, accountId, amount);
    }
}
Ghi chú. các trường hợp cạnh chẳng hạn như kiểm tra xem số dư có lớn hơn số tiền rút không được kiểm tra để đơn giản

Trong đoạn mã trên, lớp

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

3 là một mô hình lớp Java đơn giản cho tài khoản của người dùng.
final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

4 là trình truy cập cơ sở dữ liệu cho bộ sưu tập tài khoản. Phương pháp
final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

5 hoàn thành tập hợp các hoạt động được thực hiện bởi một quy trình duy nhất (P1 hoặc P2) được mô tả trong ví dụ đầu tiên để phân phối tiền cho bạn hoặc vợ/chồng của bạn

Bây giờ chúng ta sử dụng hàm

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

6 này để gọi
final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

7

.. Some REST API 
AccountService accountService = ...; // Dependency injected

@Path('/account/withdraw') // Endpoint to withdraw money
withdrawMoney() {
	ObjectId accountId = ...// some method to get current users account ID
    Account account = withTransaction(new Function() {
        @Override
        public Workflow apply(ClientSession clientSession) {
        	// Everything inside this block run with in the same transaction as long as you pass the argument clientSession to mongo
            accountService.drawCash(clientSession, accountId, 10);
        }
    });

    if(Objects.isNull(account)){
        return "Failed to withdraw money";
    }
    return "New account balance is " + account.balance;
}

Bây giờ, nếu bạn gọi điểm cuối này hai lần, đồng thời, một người dùng sẽ thấy số dư cuối cùng là 90 và người dùng thứ hai sẽ thấy 80

Bạn có thể đoán rằng giao dịch của người dùng thứ hai đã thất bại. Vâng, nó đã làm. Nhưng MongoDB có cơ chế thử lại tích hợp và nó đã tự động thử lại thao tác thứ hai của chúng tôi và thành công

Trường hợp sử dụng ví dụ trong thế giới thực

Chúng tôi sử dụng các giao dịch trên PS2PDF của mình. com chuyển đổi video trực tuyến để ngăn một luồng ghi đè trạng thái quy trình được cập nhật bởi luồng khác

Ví dụ: đối với mỗi quy trình chuyển đổi video, chúng tôi tạo một tài liệu có tên là Công việc trên DB. Nó có một trường trạng thái có thể nhận các giá trị như

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

8,
final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

9 và
static  R withTransaction(final Function executeFn) {
	final ClientSession clientSession = getNewClientSession();
	TransactionOptions txnOptions = this.getTransactionOptions();
       
	TransactionBody txnBody = new TransactionBody() {
		public R execute() {
			return executeFn.apply(clientSession);
		}
	};

	try {
		return clientSession.withTransaction(txnBody, txnOptions);
	} catch (RuntimeException e) {
		e.printStackTrace();
	} finally {
		clientSession.close();
	}
	return null;
}
0

Khi chủ đề đã cập nhật Công việc. trạng thái trên DB thành

static  R withTransaction(final Function executeFn) {
	final ClientSession clientSession = getNewClientSession();
	TransactionOptions txnOptions = this.getTransactionOptions();
       
	TransactionBody txnBody = new TransactionBody() {
		public R execute() {
			return executeFn.apply(clientSession);
		}
	};

	try {
		return clientSession.withTransaction(txnBody, txnOptions);
	} catch (RuntimeException e) {
		e.printStackTrace();
	} finally {
		clientSession.close();
	}
	return null;
}
0, chúng tôi không muốn bất kỳ chuỗi chậm nào hoàn nguyên thông báo đó thành
final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

9. Một khi công việc đã hoàn thành thì không thể thay đổi

Chúng tôi sử dụng phương pháp

final static MongoClient client; // assumed you initialized this somewhere

public static ClientSession getNewClientSession() {
    return client.startSession();
}

public static TransactionOptions getTransactionOptions() {
    return TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
}

6 đã đề cập ở trên để đảm bảo rằng không có hoạt động nào ghi đè trạng thái
static  R withTransaction(final Function executeFn) {
	final ClientSession clientSession = getNewClientSession();
	TransactionOptions txnOptions = this.getTransactionOptions();
       
	TransactionBody txnBody = new TransactionBody() {
		public R execute() {
			return executeFn.apply(clientSession);
		}
	};

	try {
		return clientSession.withTransaction(txnBody, txnOptions);
	} catch (RuntimeException e) {
		e.printStackTrace();
	} finally {
		clientSession.close();
	}
	return null;
}
4

Phần kết luận

Tôi hy vọng bây giờ bạn có thể sử dụng các giao dịch để tránh các điều kiện cạnh tranh trên các ứng dụng của mình. Ngoài ra, hãy sử dụng

static  R withTransaction(final Function executeFn) {
	final ClientSession clientSession = getNewClientSession();
	TransactionOptions txnOptions = this.getTransactionOptions();
       
	TransactionBody txnBody = new TransactionBody() {
		public R execute() {
			return executeFn.apply(clientSession);
		}
	};

	try {
		return clientSession.withTransaction(txnBody, txnOptions);
	} catch (RuntimeException e) {
		e.printStackTrace();
	} finally {
		clientSession.close();
	}
	return null;
}
5 và
static  R withTransaction(final Function executeFn) {
	final ClientSession clientSession = getNewClientSession();
	TransactionOptions txnOptions = this.getTransactionOptions();
       
	TransactionBody txnBody = new TransactionBody() {
		public R execute() {
			return executeFn.apply(clientSession);
		}
	};

	try {
		return clientSession.withTransaction(txnBody, txnOptions);
	} catch (RuntimeException e) {
		e.printStackTrace();
	} finally {
		clientSession.close();
	}
	return null;
}
6 tích hợp sẵn để cải thiện khả năng chịu lỗi

Tôi nên chỉ ra rằng, Giao dịch MongoDB còn khá mới và có những bài viết xác định một số điểm không nhất quán xảy ra trong các trường hợp đặc biệt. Nhưng rất có thể bạn sẽ gặp phải những vấn đề này

QUẢNG CÁO

QUẢNG CÁO

QUẢNG CÁO

QUẢNG CÁO

QUẢNG CÁO

QUẢNG CÁO

QUẢNG CÁO


Chúng tôi có thể sử dụng MongoDB cho các giao dịch không?
Haritha Yahathugoda

Đọc thêm bài viết


Nếu bài viết này hữu ích, hãy tweet nó

Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu

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.

Làm cách nào để tạo giao dịch trong MongoDB?

Các giao dịch trong MongoDB tuân thủ các nguyên tắc ACID này và có thể được sử dụng một cách đáng tin cậy trong các trường hợp cần thay đổi nhiều tài liệu trong một lần. .
Bước 1 — Chuyển đổi phiên bản MongoDB độc lập của bạn thành một bộ bản sao. .
Bước 2 — Chuẩn bị dữ liệu mẫu. .
Bước 3 — Tạo giao dịch hoàn chỉnh đầu tiên của bạ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.

MongoDB không phù hợp với những tình huống nào?

Một trong những nhược điểm của MongoDB là không hỗ trợ giao dịch . Mặc dù ngày càng có ít ứng dụng yêu cầu giao dịch nhưng vẫn có một số ứng dụng cần giao dịch để cập nhật nhiều tài liệu/bộ sưu tập. Nếu đó là chức năng cần thiết cho nhóm của bạn thì không nên sử dụng MongoDB.