Disk penuh adalah kegagalan infrastruktur yang menyerang database dengan cara paling langsung: mongod berhenti menulis, lalu berhenti berjalan. Berbeda dari galat query atau koneksi yang punya pesan spesifik, masalah penyimpanan menuntut kita melihat dua dunia sekaligus — berkas fisik di sistem operasi dan angka logis di dalam database. Chapter ini memeriksa keduanya di mesin latihan: sisa ruang lewat df dan db.stats(), efek kompresi WiredTiger lewat perbandingan dataSize versus storageSize, lalu menutup dengan prosedur saat hal terburuk terjadi — disk penuh, izin berkas salah, dan dugaan kerusakan data.

Peta materi Chapter ini:

  • Pemeriksaan dua dunia: df -h dari OS, db.stats() dari dalam database.
  • dataSize versus storageSize — kenapa ukuran logis dan fisik berbeda jauh.
  • Prosedur disk penuh dan masalah izin di dbPath.
  • Dugaan kerusakan data: tanda, verifikasi, dan urutan pemulihan yang benar.

Berapa Sisa Ruang: Dua Sudut Pandang #

Dari shell, df -h pada direktori data adalah pemeriksaan pertama:

bash
df -h /home/z/my-project/mongo-data

Output yang Dihasilkan:

text
Filesystem                               Size  Used Avail Use% Mounted on
c-6ad366ea-145cf406-1e00df7b3d2b-rootfs  9.9G  2.2G  7.2G  23% /

Kolom yang berarti bagi MongoDB: Avail — ruang yang masih bisa ditulis — dan Use% yang merambat naik. Dari dalam database, angka yang sama bisa dibaca tanpa membuka shell, lengkap dengan pemakaian versi MongoDB sendiri. Kita siapkan dulu collection arsip berisi data repetitif sebagai bahan perbandingan:

js
use latihan_trouble
db.arsip.drop()
const docs = []
for (let i = 0; i < 2000; i++) {
  docs.push({ rak: "R" + (i % 20), kategori: "novel", status: "tersedia", catatan: "Stok reguler siap kirim ke seluruh cabang toko", stok: i % 30 })
}
const hasil = db.arsip.insertMany(docs)
print("jumlah document arsip: " + db.arsip.countDocuments({}) + ", acknowledged: " + hasil.acknowledged)
db.stats({ scale: 1024 * 1024 })

Output yang Dihasilkan:

text
switched to db latihan_trouble
true

2000

jumlah document arsip: 2000, acknowledged: true

{
  db: 'latihan_trouble',
  collections: Long('6'),
  views: Long('0'),
  objects: Long('7010'),
  avgObjSize: 110.55178316690443,
  dataSize: 0.7390670776367188,
  storageSize: 0.24609375,
  indexes: Long('7'),
  indexSize: 0.3828125,
  totalSize: 0.62890625,
  scaleFactor: Long('1048576'),
  fsUsedSize: 2696.27734375,
  fsTotalSize: 10043.26953125,
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1792279678, i: 5 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1792279678, i: 5 })
}

Field fsUsedSize dan fsTotalSize adalah padanan Used dan Size dari df (pembulatannya sedikit berbeda karena satuan MiB versus GiB) — angka ini yang layak dipantau berkala karena berlaku untuk seluruh dbPath, bukan satu database. Baris 2000 sebelum print adalah nilai akhir ekspresi docs.push(...) di loop; baris true di awal adalah hasil drop(). Perhatikan juga indexSize: index ikut memakan disk, dan pada database dengan banyak index, indexSize bisa melebihi storageSize data itu sendiri. Angka objects di sini mencakup seluruh collection latihan kita di database ini.

dataSize versus storageSize: Kompresi WiredTiger #

Pasangan field paling sering disalahpahami: dataSize adalah ukuran logis document seolah tak terkompresi, storageSize adalah ruang fisik yang benar-benar dipakai di disk setelah kompresi block WiredTiger. Kita bedah collection arsip saja:

js
const s = db.arsip.stats({ scale: 1024 * 1024 })
({ ns: s.ns, jumlah: s.count, dataSize: s.size, storageSize: s.storageSize, totalIndexSize: s.totalIndexSize, totalSize: s.totalSize })

Output yang Dihasilkan:

text
{
  ns: 'latihan_trouble.arsip',
  jumlah: 2000,
  dataSize: 0.27751922607421875,
  storageSize: 0.00390625,
  totalIndexSize: 0.00390625,
  totalSize: 0.0078125
}

Dua ribu document berukuran logis 0,28 MB hanya memakan sekitar 4 KB di disk — rasio pemadatan ekstrem karena isinya sangat repetitif (kategori, status, dan catatan yang sama berulang). Data production yang lebih beragam biasanya berada di rasio yang jauh lebih rendah, tetapi arah kesimpulannya sama: ukuran data menurut aplikasi bukan ukuran data menurut disk. Konsekuensinya dua arah: kapasitas tidak bisa dihitung dari estimasi ukuran document mentah, dan storageSize yang jauh di bawah dataSize adalah tanda kompresi bekerja normal — bukan gejala hilangnya data.

Disk Penuh: Ketika mongod Berhenti #

Urutan kejadiannya khas: ruang Avail menyentuh nol, operasi write mulai gagal dengan galat tingkat sistem operasi, WiredTiger menolak melanjutkan tanpa jaminan bisa menulis, dan mongod berhenti — sering kali dengan pesan no space left on device di log sebelum proses keluar. Gejala di production yang perlu dikenali: aplikasi mendadak gagal write di semua collection sekaligus.

Urutan pemulihannya penting. Pertama, pulihkan ruang di luar MongoDB bila ada (log aplikasi yang membengkak, berkas sementara) — jangan pernah menghapus berkas di dalam dbPath secara manual. Kedua, dari dalam database: hapus index tak terpakai (mengembalikan indexSize), terapkan TTL index untuk data kedaluwarsa otomatis, atau jalankan compact pada collection terbesar di jam sepi. Ketiga, bila pertumbuhannya struktural, pindahkan dbPath ke disk lebih besar — prosedurnya dibahas di Section Backup dan Recovery.

dbPath dan Izin Berkas #

mongod membaca-mengubah berkas di dbPath sepanjang hidupnya, jadi izin berkas adalah syarat hidup:

bash
ls -ld /home/z/my-project/mongo-data

Output yang Dihasilkan:

text
drwxrwxr-x 5 z z 53248 Oct 17 23:27 /home/z/my-project/mongo-data

Pembacaannya mengikuti notasi izin Unix: pemilik z memiliki rwx, grup z juga rwx, dan pengguna lainnya hanya r-x. Pada mesin latihan proses mongod berjalan sebagai pengguna z — cocok dengan pemilik dbPath. Gejala klasik di mesin baru: mongod menolak menyala dengan Permission denied di log karena dbPath dibuat lewat sudo sehingga dimiliki root, sementara service dijalankan user lain. Perbaikannya satu perintah chown — bukan menyalakan ulang berulang kali.

Dugaan Kerusakan Data: Urutan yang Benar #

Tanda-tandanya di log: mongod berhenti tidak wajar (listrik, kill -9), lalu saat dinyalakan ulang ia berulang kali keluar sendiri dengan pesan kerusakan berkas WiredTiger. Sebelum melakukan apa pun selain memverifikasi — satu prinsip: backup dulu, baru perbaiki. Salin seluruh dbPath (dalam keadaan mati) atau mongodump yang masih bisa dibaca, baru kemudian jalankan mongod --repair yang membangun ulang berkas data; perbaikan ini bisa membuang document yang berkasnya rusak, sehingga menjalankannya tanpa backup adalah keputusan yang tidak bisa dibatalkan.

Untuk kecurigaan ringan tanpa gejala berhenti, db.arsip.validate() memeriksa konsistensi struktur, index, dan data sebuah collection lalu melaporkan temuannya — jalankan pada collection yang dicurigai, bukan pada seluruh database. Verifikasi cadangan berkala adalah satu-satunya cara tahu backup benar-benar bisa dipulihkan.

GejalaPenyebab umumTindakan
Write gagal di semua collection mendadakDisk penuh (Avail nol)Pulihkan ruang; audit indexSize; compact di jam sepi
mongod tidak mau menyala, log Permission denieddbPath dimiliki user lainchown dbPath ke user yang menjalankan mongod
mongod keluar berulang setelah crashKerusakan berkas WiredTigerBackup dbPath dulu, baru --repair
storageSize jauh di bawah dataSizeKompresi WiredTiger normalTidak perlu tindakan — itu perilaku yang benar
Kapasitas habis meski data “kecil”Banyak index; data historis menumpukTinjau indexSize; TTL index; arsipkan
Angka fsUsedSize naik terus tanpa write besarJournal dan ruang internal belum dikembalikanJadwalkan compact; pantau tren, bukan satu titik

Rangkuman #

  • Pemeriksaan penyimpanan selalu dua sisi: df -h dari OS, db.stats() dari database — keduanya harus cocok.
  • dataSize adalah ukuran logis, storageSize ukuran fisik pasca-kompresi; selisih besar adalah normal.
  • Disk penuh dimitigasi dengan urutan aman: pulihkan ruang, hapus index tak terpakai, compact, lalu pertimbangkan disk lebih besar.
  • Izin dbPath yang salah membuat mongod menolak menyala; perbaikannya chown, bukan restart berulang.
  • Kerusakan data: backup dulu, --repair kemudian, validate() untuk kecurigaan ringan.