Saat Row Database Selamat tapi File-nya Tidak: Masalah Orphaned Blob

Saat Row Database Selamat tapi File-nya Tidak: Masalah Orphaned Blob
Sekitar 400 file media lenyap dari object storage di sebuah sistem operasional hotel yang saya kerjakan, padahal database-nya sehat sempurna. Row yang merujuknya selamat; byte yang dirujuknya tidak. Cuma 45% yang berhasil kembali.
Semua backup hijau, semua migrasi terpasang, semua row utuh. Tapi foto lampiran laporan maintenance, bukti insiden, dan dokumentasi housekeeping begitu saja hilang. Tak ada yang sadar sampai seorang pengguna membuka laporan lama dan mendapat gambar rusak.
Inilah masalah orphaned blob. Versinya ada di hampir semua sistem yang menyimpan row di database dan file di disk atau bucket.
Bagaimana file lenyap sementara row selamat
Database itu transaksional. File store bukan bagian dari transaksinya. Satu fakta arsitektural itu melahirkan semua varian kegagalannya:
- Migrasi storage memindahkan file antar server atau bucket dan menjatuhkan sebagian di jalan, tanpa error muncul di mana pun aplikasi melihat.
- Script cleanup dengan cakupan sedikit meleset menghapus file yang masih dirujuk row aktif.
- Aturan lifecycle bucket meng-expire objek yang seseorang kira permanen.
- Upload gagal setelah row terlanjur commit, meninggalkan referensi ke file yang tidak pernah ada sama sekali.
Tidak satu pun dari itu menghasilkan error database. Bayangkan database dan file store sebagai dua petugas terpisah yang tidak saling lapor: satu menjaga daftar tamu, satu menjaga kunci kamar. Referential integrity di dalam PostgreSQL ditegakkan oleh engine. Referential integrity antara PostgreSQL dan file store tidak ditegakkan siapa-siapa — kecuali Anda membangun job yang menegakkannya.
Manifest rekonsiliasi
Pemulihan dimulai dari mengetahui bentuk kerusakan secara persis. Alatnya adalah manifest tiga arah, dibangun dari satu-satunya sumber kebenaran yang tersedia:
Daftar semua path file yang dirujuk row. Daftar semua objek yang benar-benar dipegang storage. Daftar seluruh isi mirror backup.
Join-nya mengklasifikasi tiap file ke salah satu dari empat kelompok. Mendadak keluhan kabur "ada gambar yang rusak" berubah jadi perintah kerja presisi: restore yang ini, relakan yang itu, review orphan-nya.
Seperti apa pemulihannya
Sekitar 45% file yang hilang kembali dari mirror backup — salinan lama volume storage yang kebetulan lebih tua dari momen kehilangan. Sisa 55%-nya lenyap permanen, dan alasannya gamblang: backup cuma mencakup database.
Row yang mendeskripsikan tiap file (nama file, tanggal upload, laporan mana pemiliknya) terawetkan rapi. File-nya sendiri tidak pernah masuk cakupan backup mana pun. Sistem itu rajin melindungi pointer sambil mengabaikan apa yang ditunjuknya.
Pemulihan parsial semacam itu adalah hasil tipikal, bukan skenario terburuk. Tanpa manifest, fraksi yang terpulihkan pun ikut hilang, karena tak ada yang tahu file mana harus dicari di mirror mana.
Pelajaran yang berlaku umum
Object storage masuk cakupan backup. File yang dirujuk row database adalah data bisnis dengan ekonomi penyimpanan berbeda — tidak lebih. Backup dengan jadwal dan retensi yang sama dengan database, dan verifikasi keduanya di uji restore yang sama. Disiplinnya saya bahas di pg_dump Anda bukan backup sebelum pernah di-restore.
Tulis file dulu, commit row belakangan. Pola upload-then-commit membuat mode gagalnya jinak: kalau upload gagal, tidak ada row yang merujuk file hilang; kalau commit gagal, Anda dapat orphaned blob — ruang terbuang, bukan referensi rusak.
Penghapusan menjalankan logika yang sama terbalik: hapus row dulu, biarkan job cleanup memungut file tak terujuk belakangan. Di antara dua mode gagal itu, orphan jauh lebih murah daripada referensi menggantung. Susun urutan tulisnya agar orphan satu-satunya jenis yang mungkin Anda hasilkan.
Jalankan rekonsiliasi terus-menerus. Manifest yang menggerakkan pemulihan itu seharusnya tidak pernah jadi barang sekali pakai. Sebagai job mingguan biayanya cuma listing dan set-diff, dan ia mengubah pergeseran senyap menjadi alert selagi kerugian masih kecil dan masih di dalam retensi backup. Hitungan file hilang yang naik dari nol adalah sistem peringatan dini untuk semua kelas kegagalan di atas.
Media adalah data bisnis. Insting yang menghilangkan file-file ini adalah keyakinan bahwa "data sesungguhnya ada di database" dan file cuma hiasan. Di sistem manajemen hotel, foto maintenance adalah bukti penyelesai sengketa. Lampiran insiden adalah sandaran klaim asuransi.
Row dan file adalah satu dataset yang kebetulan tinggal di dua tempat. Seluruh sistem, dari backup sampai pemeriksaan integritas, harus memperlakukannya begitu.
Artikel Terkait
Mau bangun hal serupa?
Jasa Pengembangan Backend IoT & Integrasi Multi-Protokol
Backend yang menyerap telemetri perangkat lintas MQTT, WebSocket, Modbus, dan BLE, lalu menyatukannya jadi dashboard real-time yang andal.
Lihat cara saya bisa bantu