Home / Artikel / Web Development
Web Development

Soft Delete di MySQL: Data Terhapus, tetapi Bisnis Tetap Punya Jalan Pulang

Menghapus data secara permanen sering terlihat sederhana, sampai pengguna salah klik atau tim membutuhkan kembali catatan lama. Soft delete memberi aplikasi cara untuk menyembunyikan data tanpa langsung memusnahkannya.

Soft Delete di MySQL: Data Terhapus, tetapi Bisnis Tetap Punya Jalan Pulang

Tombol hapus tidak selalu berarti data harus benar-benar hilang dari database. Dalam aplikasi toko online, sistem keanggotaan, helpdesk, atau manajemen dokumen, data yang tampak tidak terpakai hari ini bisa kembali dibutuhkan beberapa minggu kemudian.

Di sinilah soft delete berguna. Alih-alih menjalankan DELETE dan menghapus baris secara permanen, aplikasi menandai data sebagai tidak aktif—biasanya dengan kolom deleted_at. Data tersebut tidak lagi muncul dalam tampilan normal, tetapi masih tersedia untuk pemulihan, audit, atau proses penghapusan permanen yang dilakukan secara terencana.

Apa itu soft delete?

Soft delete adalah pola penghapusan data dengan mengubah status atau waktu penghapusan, bukan langsung membuang baris dari tabel.

Contoh struktur tabel sederhana:

CREATE TABLE customers (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(150) NOT NULL,
    email VARCHAR(190) NOT NULL,
    deleted_at DATETIME NULL,
    created_at DATETIME NOT NULL,
    updated_at DATETIME NOT NULL
);

Jika deleted_at bernilai NULL, data dianggap masih aktif. Jika berisi waktu tertentu, data dianggap sudah dihapus secara logis.

Pendekatan ini berbeda dari menambahkan kolom seperti is_deleted dengan nilai 0 atau 1. Keduanya bisa digunakan, tetapi deleted_at biasanya memberi informasi tambahan: kapan data dihapus dan siapa tahu, informasi tersebut dapat berguna saat menyelidiki masalah.

Mengapa tidak langsung memakai DELETE?

Penghapusan permanen memang lebih sederhana pada awalnya. Namun, konsekuensinya bisa merepotkan.

  • Data sulit dipulihkan ketika pengguna salah menghapus.
  • Riwayat transaksi bisa kehilangan referensi ke data lama.
  • Tim dukungan tidak dapat memeriksa kondisi sebelum data hilang.
  • Audit menjadi lebih sulit karena tidak ada jejak bahwa data pernah ada.
  • Relasi antar-tabel dapat rusak jika data induk dihapus lebih dahulu.

Misalnya, seorang pelanggan menghapus akunnya, tetapi pesanan dan invoice lama tetap perlu disimpan. Jika baris pelanggan dihapus secara permanen, aplikasi mungkin kehilangan nama atau identitas yang dibutuhkan untuk menampilkan riwayat transaksi.

Soft delete tidak menyelesaikan semua persoalan, tetapi memberi jarak antara keputusan “sembunyikan dari aplikasi” dan “musnahkan dari penyimpanan”. Jarak ini penting ketika kesalahan masih mungkin diperbaiki.

Implementasi dasar di PHP dan MySQL

Untuk menghapus data secara logis, aplikasi cukup memperbarui kolom waktu:

UPDATE customers
SET deleted_at = NOW(), updated_at = NOW()
WHERE id = :id AND deleted_at IS NULL;

Query untuk menampilkan data aktif harus selalu menyertakan filter:

SELECT id, name, email
FROM customers
WHERE deleted_at IS NULL
ORDER BY created_at DESC;

Dengan PDO, parameter tetap perlu digunakan agar nilai dari pengguna tidak langsung digabungkan ke string SQL:

$stmt = $pdo->prepare(
    'UPDATE customers
     SET deleted_at = NOW(), updated_at = NOW()
     WHERE id = :id AND deleted_at IS NULL'
);

$stmt->execute(['id' => $customerId]);

Kesalahan yang sering terjadi adalah hanya menerapkan filter pada satu halaman. Halaman daftar sudah benar, tetapi endpoint pencarian, laporan admin, atau API masih menampilkan data yang telah dihapus. Karena itu, aturan “hanya data aktif” sebaiknya dibuat konsisten di lapisan akses data, bukan mengandalkan ingatan setiap programmer.

Jangan lupa fitur restore

Soft delete paling berguna jika aplikasi menyediakan cara untuk memulihkan data. Query pemulihannya sederhana:

UPDATE customers
SET deleted_at = NULL, updated_at = NOW()
WHERE id = :id AND deleted_at IS NOT NULL;

Namun, restore bukan sekadar tombol. Aplikasi perlu memikirkan konflik yang mungkin muncul. Contohnya, alamat email pelanggan yang dihapus kemudian dipakai akun baru. Ketika akun lama dipulihkan, aturan unik pada kolom email bisa menyebabkan proses gagal.

Karena itu, sebelum restore, sistem sebaiknya memeriksa apakah data yang dibutuhkan masih tersedia dan apakah aturan bisnis masih terpenuhi. Jika tidak, tampilkan alasan yang jelas kepada admin, bukan pesan error database yang sulit dipahami.

Masalah unik: email, username, dan kode produk

Soft delete sering menimbulkan pertanyaan tentang unique constraint. Apakah email dari data yang dihapus boleh dipakai lagi? Jawabannya bergantung pada kebutuhan aplikasi.

Jika email harus tetap unik termasuk di antara akun yang dihapus, indeks unik biasa dapat dipertahankan. Namun, jika email boleh digunakan oleh akun baru setelah akun lama dihapus, desain tabel harus mendukung aturan tersebut.

Salah satu pendekatan adalah memindahkan data lama ke tabel arsip. Pendekatan lain adalah menggunakan kolom khusus yang membedakan data aktif dan terhapus, tetapi penerapannya perlu disesuaikan dengan database serta versi MySQL yang digunakan. Jangan menonaktifkan constraint hanya demi membuat error hilang, karena hal itu bisa menghasilkan data ganda yang sulit dibereskan.

Soft delete bukan pengganti kebijakan retensi

Data yang ditandai terhapus tetap memakan ruang dan mungkin masih mengandung informasi pribadi. Karena itu, soft delete perlu dilengkapi kebijakan retensi: berapa lama data disimpan, siapa yang boleh memulihkan, dan kapan data benar-benar dimusnahkan.

Contoh proses pembersihan berkala:

DELETE FROM customers
WHERE deleted_at IS NOT NULL
  AND deleted_at < NOW() - INTERVAL 2 YEAR;

Query seperti ini tidak boleh dijalankan sembarangan. Pastikan sudah ada backup, pemeriksaan relasi, dan persetujuan sesuai kebutuhan bisnis. Untuk data sensitif, penghapusan permanen juga harus dipertimbangkan dari sisi kebijakan privasi dan kewajiban penyimpanan data.

Checklist sebelum menerapkan soft delete

  • Gunakan nama kolom yang konsisten, misalnya deleted_at.
  • Tambahkan filter data aktif pada semua query daftar, pencarian, laporan, dan API.
  • Sediakan mekanisme restore yang hanya dapat diakses oleh peran berwenang.
  • Catat siapa yang menghapus dan memulihkan data jika audit dibutuhkan.
  • Periksa aturan unik untuk email, username, nomor invoice, dan kode lainnya.
  • Tentukan jadwal pembersihan permanen untuk data yang sudah lama dihapus.
  • Uji relasi antar-tabel agar penghapusan logis tidak menghasilkan data yatim.

Apa artinya bagi kita?

Soft delete bukan aturan bahwa semua data harus disimpan selamanya. Ini adalah cara merancang aplikasi agar kesalahan yang masih bisa diperbaiki tidak langsung berubah menjadi kehilangan data permanen.

Gunakan soft delete untuk data yang punya nilai historis, terhubung dengan transaksi, atau mungkin perlu dipulihkan. Untuk data sementara yang tidak penting dan tidak memiliki relasi, penghapusan permanen bisa lebih masuk akal. Keputusan terbaik bukan yang paling mudah ditulis dalam satu query, melainkan yang paling sesuai dengan risiko dan siklus hidup data di aplikasi.

– Rio Yotto @rioyotto