Cơn ác mộng Log lúc 2 giờ sángBạn vừa triển khai một tính năng thông báo thời gian thực xịn xò. Trên lý thuyết, mọi thứ trông thật hoàn hảo. Nhưng ngay khi dịch vụ của bạn truy cập vào cơ sở dữ liệu, các bản log bùng nổ với lỗi này:
MongoServerError: The $changeStream stage is only supported on replica sets or sharded clusters
Điều này xảy ra do môi trường local hoặc server thử nghiệm của bạn có khả năng đang chạy một standalone MongoDB instance. Standalone instances là mặc định của nhiều trình cài đặt, nhưng chúng thiếu Oplog (Operations Log). Vì Change Streams phụ thuộc hoàn toàn vào Oplog để phát các sự kiện dữ liệu, chúng đơn giản là sẽ không hoạt động nếu thiếu nó.
Cách khắc phục nhanh (TL;DR)Bạn phải chuyển đổi MongoDB standalone của mình thành một replica set nút đơn (single-node replica set). Ngay cả khi bạn không có kế hoạch thêm server thứ hai, MongoDB vẫn yêu cầu cơ chế replication phải hoạt động để kích hoạt Change Streams. Quá trình này thường mất chưa đầy 60 giây.
- Khởi động lại tiến trình
mongodvới cờ--replSet:mongod --replSet rs0- Mởmongoshvà chạy:rs.initiate()## Tại sao điều này xảy raCác bản cài đặt tiêu chuẩn trên macOS (Homebrew), Windows, hoặc Ubuntu khởi động MongoDB như một tiến trình đơn lẻ, độc lập. Việc này giúp tiết kiệm khoảng 5% dung lượng đĩa bằng cách bỏ qua việc tạo Oplog. Tuy nhiên, Change Streams hoạt động bằng cách "tailing" (theo dõi) Oplog. Không có Oplog? Không có stream. Bằng cách bật replication, bạn yêu cầu MongoDB bắt đầu ghi lại mọi thao tác ghi vào một collection ẩn, nơi mà Change Stream sau đó sẽ theo dõi.
Khắc phục trên các bản cài đặt LocalNếu bạn không sử dụng Docker và cài đặt MongoDB trực tiếp trên máy của mình, hãy làm theo các bước sau.
1. Cập nhật cấu hình của bạnMở tệp mongod.conf của bạn. Nếu bạn sử dụng Homebrew trên máy Mac chạy chip Apple Silicon, tệp này thường nằm tại /opt/homebrew/etc/mongod.conf. Trên Linux, hãy kiểm tra /etc/mongod.conf. Thêm hai dòng sau:
replication:
replSetName: "rs0"
2. Khởi động lại cơ sở dữ liệuÁp dụng cấu hình mới bằng cách khởi động lại dịch vụ.
# Dành cho người dùng macOS
brew services restart mongodb-community
# Dành cho người dùng Linux
sudo systemctl restart mongod
3. Kích hoạt Replica SetTruy cập vào MongoDB shell bằng cách gõ mongosh. Chạy lệnh khởi tạo:
rs.initiate()
Đợi khoảng 3 đến 5 giây. Dấu nhắc lệnh của bạn sẽ thay đổi từ test> thành rs0 [direct: primary] test>. Hiện tại bạn đang chạy một single-node replica set.
Khắc phục trong môi trường Docker ComposeCác Docker image tiêu chuẩn như mongo:latest khởi động ở chế độ standalone. Để khắc phục điều này trong quy trình phát triển của bạn, hãy sử dụng thiết lập docker-compose.yml để xử lý việc khởi tạo tự động. Điều này giúp tránh bước rs.initiate() thủ công mỗi khi bạn xóa các volume.
services:
mongo:
image: mongo:6.0
command: ["--replSet", "rs0", "--bind_ip_all"]
ports:
- "27017:27017"
healthcheck:
test: "mongosh --eval 'rs.initiate()' || exit 0"
interval: 10s
timeout: 5s
retries: 5
Lưu ý đoạn || exit 0 trong healthcheck. Điều này ngăn container báo lỗi nếu rs.initiate() được gọi trên một cơ sở dữ liệu đã được khởi tạo trước đó.
Xác nhận khắc phục thành côngViệc kiểm tra sửa lỗi rất đơn giản. Tạo một tệp tên là watch.js và dán đoạn mã Node.js này vào:
const { MongoClient } = require('mongodb');
async function run() {
const uri = 'mongodb://localhost:27017/?replicaSet=rs0';
const client = new MongoClient(uri);
await client.connect();
console.log('Connected. Watching testdb.orders...');
const stream = client.db('testdb').collection('orders').watch();
stream.on('change', (change) => {
console.log('Event detected:', change.operationType, change.fullDocument);
});
}
run().catch(console.error);
Chạy node watch.js. Thêm một document vào collection orders bằng GUI hoặc shell của bạn. Nếu sự kiện xuất hiện trong terminal, lỗi đã chính thức được giải quyết.

