Khắc phục lỗi MongoDB: '$changeStream stage is only supported on replica sets'

intermediate🍃 MongoDB2026-04-26| MongoDB (phiên bản 4.0 đến 7.0), các driver Node.js/Python/Go và môi trường phát triển dựa trên Docker.

Error Message

MongoServerError: The $changeStream stage is only supported on replica sets or sharded clusters
#mongodb#change-streams#replica-set#devops#docker

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 mongod với cờ --replSet: mongod --replSet rs0- Mở mongosh và 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.

Các thực hành tốt nhất và Hiệu suấtTrước khi đưa vào môi trường production, hãy lưu ý hai điều. Thứ nhất, cập nhật chuỗi kết nối (connection string) của ứng dụng. Nó phải bao gồm tham số replicaSet=rs0 để driver biết cách kết nối với set một cách chính xác. Thứ hai, theo dõi dung lượng đĩa của bạn. Oplog là một capped collection; nó sẽ không tăng trưởng mãi mãi, nhưng nó yêu cầu một phần dung lượng lưu trữ được cấp phát trước. Đối với các ứng dụng có lưu lượng truy cập cao, Oplog từ 10GB đến 50GB là phổ biến để đảm bảo bạn không mất dấu các thay đổi trong những lần gián đoạn mạng ngắn.

Đọc thêm- Tài liệu chính thức về MongoDB Change Streams- Chi tiết về việc chuyển đổi Standalone sang Replica Set

Related Error Notes