Sửa lỗi MongoDB 'Write concern specified was not met' trong Replica Sets

intermediate🍃 MongoDB2026-05-02| MongoDB 4.0+ chạy trong một Replica Set (Linux, Docker, hoặc Atlas)

Error Message

Write concern specified was not met
#mongodb#replica set#quản trị cơ sở dữ liệu#khắc phục sự cố

TL;DR: Cách khắc phục nhanh

Lỗi này có nghĩa là yêu cầu ghi của bạn đã đến node Primary, nhưng các node Secondary đã không xác nhận việc lưu trữ đủ nhanh. Bộ đếm thời gian (wtimeout) đã hết hạn trước khi nhận được phản hồi từ các node khác.

Hãy thử các bước sau trước:

  • Kiểm tra trạng thái node: Chạy rs.status() trong shell. Tất cả các node phải ở trạng thái PRIMARY hoặc SECONDARY. Một node bị kẹt ở trạng thái RECOVERING sẽ không xác nhận các yêu cầu ghi.
  • Tăng timeout: Nếu ứng dụng của bạn sử dụng wtimeout: 1000 (1 giây), hãy thử tăng lên 5000. Các đợt lưu lượng truy cập cao thường cần hơn một giây để dữ liệu được truyền đi trong mạng.
  • Xác minh đa số (majority): Nếu bạn đang sử dụng w: "majority" trên một bộ 3 node, bạn phải có ít nhất 2 node chứa dữ liệu hoạt động bình thường.

Tại sao lỗi này xuất hiện

MongoDB không chỉ 'ghi rồi quên' khi bạn sử dụng replica sets. Bạn thường muốn có sự đảm bảo rằng dữ liệu được an toàn trên nhiều máy tính. Khi bạn chỉ định một write concern như majority, node Primary sẽ đợi các node Secondary kéo dữ liệu vào oplog cục bộ của chúng và gửi lại một xác nhận (ACK).

Nếu thông báo 'Write concern specified was not met' xuất hiện, việc ghi thực tế đã thành công trên Primary, nhưng cluster đã không đáp ứng được các yêu cầu an toàn của bạn kịp lúc. Dưới đây là những gì thường xảy ra:

  • Độ trễ sao chép (Replication Lag) lớn: Nếu các node Secondary gặp phải tình trạng chờ I/O đĩa cao (thường là 10% trở lên), chúng sẽ bị chậm lại. Thậm chí độ trễ 2 giây cũng sẽ kích hoạt một wtimeout 1 giây.
  • Mạng chập chờn (Network Flapping): Các sự cố ngắt quãng nhỏ giữa các trung tâm dữ liệu có thể làm chậm các gói tin xác nhận, ngay cả khi các node về mặt kỹ thuật vẫn đang 'hoạt động'.
  • Tranh chấp tài nguyên: Việc tạo index chạy ngầm hoặc một truy vấn aggregation nặng trên một node Secondary có thể làm cạn kiệt chu kỳ CPU của quá trình sao chép.

Các bước khắc phục sự cố

1. Kiểm tra sức khỏe Cluster

Bắt đầu bằng cách xác định bất kỳ node 'thây ma' nào. Truy cập vào Mongo shell và kiểm tra nhịp tim (heartbeats):

rs.status()

Kiểm tra đầu ra để tìm health: 0 hoặc các trạng thái như STARTUP2. Nếu một node bị thiếu, nó sẽ vô hình đối với logic write concern. Một nguyên nhân phổ biến là node bị hết dung lượng đĩa và ngừng đồng bộ hoàn toàn.

2. Định lượng độ trễ

Một node 'khỏe mạnh' vẫn có thể chậm. Hãy kiểm tra chính xác các node Secondary đang chậm hơn node Primary bao nhiêu giây:

rs.printSecondaryReplicationInfo()

Nếu bạn thấy 5 secs behind the primary nhưng mã ứng dụng của bạn sử dụng wtimeout: 2000, bạn đã tìm thấy nút thắt cổ chai. Bạn có thể cần bộ lưu trữ NVMe nhanh hơn hoặc một khoảng thời gian timeout nới lỏng hơn.

3. Điều chỉnh mã ứng dụng

Trong nhiều trường hợp, cluster vẫn ổn về mặt vật lý, nhưng ứng dụng lại quá 'nóng vội'. Dưới tải nặng, việc sao chép đương nhiên sẽ mất nhiều thời gian hơn. Hãy để cluster của bạn có thêm khoảng trống để xử lý bằng cách điều chỉnh cài đặt write concern trong driver.

Node.js (Mongoose):

// Tăng wtimeout từ mặc định lên 5 giây
await User.create([{ name: 'Alice' }], { 
  writeConcern: { 
    w: 'majority', 
    wtimeout: 5000 
  } 
});

Python (PyMongo):

from pymongo import WriteConcern

# Áp dụng timeout 5 giây cho một thao tác cụ thể
coll.with_options(
    write_concern=WriteConcern(w='majority', wtimeout=5000)
).insert_one({'trạng thái': 'đang hoạt động'})

4. Kiểm tra quyền bầu chọn của node

Chạy rs.conf() và tìm trường votes. Nếu bạn có năm node nhưng ba node được cấu hình với votes: 0, các tính toán 'majority' có thể hoạt động không như mong đợi. Đảm bảo tất cả các node chứa dữ liệu mà bạn mong đợi xác nhận việc ghi thực sự được phép bầu chọn.

Kiểm tra giải pháp

Đừng chỉ hy vọng cách sửa lỗi sẽ hoạt động. Hãy kiểm tra nó trong shell bằng cách sử dụng các cài đặt an toàn cho môi trường sản xuất của bạn:

db.heartbeat.insertOne(
  { ts: new Date() }, 
  { writeConcern: { w: "majority", wtimeout: 10000 } }
)

Nếu lệnh này trả về acknowledged: true ngay lập tức, cluster của bạn đang hoạt động tốt. Nếu nó bị treo trong vài giây trước khi hoàn tất, bạn vẫn còn các vấn đề về phần cứng hoặc nghẽn mạng cần được giải quyết.

Tìm hiểu sâu hơn

Related Error Notes