Home / Artikel / Web Development
Web Development

Soft Delete di MySQL: Cara Menghapus Data tanpa Kehilangan Jejak

Menghapus data secara permanen sering terlihat sederhana, sampai pengguna membutuhkan data itu kembali atau tim perlu menelusuri riwayat perubahan. Soft delete memberi jalan tengah, tetapi harus dirancang dengan aturan…

Soft Delete di MySQL: Cara Menghapus Data tanpa Kehilangan Jejak

Tombol hapus biasanya menjadi bagian paling sederhana dalam sebuah aplikasi. Pengguna menekan tombol, server menjalankan DELETE, lalu data menghilang. Masalah muncul ketika data yang terhapus ternyata masih dibutuhkan: pesanan perlu diperiksa, akun harus dipulihkan, atau tim ingin mengetahui siapa yang pernah mengubah catatan tersebut.

Di sinilah soft delete berguna. Alih-alih benar-benar menghapus baris dari database, aplikasi menandainya sebagai tidak aktif. Data tetap tersimpan, tetapi tidak lagi ditampilkan dalam daftar normal.

Apa itu soft delete?

Soft delete adalah pola penghapusan data dengan menambahkan penanda, biasanya berupa kolom seperti deleted_at, is_deleted, atau status. Ketika pengguna menghapus data, aplikasi tidak menjalankan penghapusan permanen. Aplikasi hanya mengubah nilai penanda tersebut.

Contoh sederhana pada tabel users:

ALTER TABLE users
ADD COLUMN deleted_at DATETIME NULL;

Data yang masih aktif memiliki nilai deleted_at berupa NULL. Saat dihapus, kolom tersebut diisi waktu penghapusan:

UPDATE users
SET deleted_at = NOW()
WHERE id = 42;

Query untuk menampilkan pengguna aktif kemudian perlu menyertakan syarat tambahan:

SELECT id, name, email
FROM users
WHERE deleted_at IS NULL;

Secara fisik, barisnya masih ada. Secara bisnis, data tersebut dianggap sudah tidak aktif.

Mengapa tidak langsung memakai DELETE?

Penghapusan permanen tetap memiliki tempat. Namun, untuk banyak aplikasi, data tidak selalu boleh hilang begitu saja. Ada beberapa alasan praktis untuk memakai soft delete.

  • Pemulihan kesalahan pengguna. Data yang tidak sengaja dihapus masih dapat dikembalikan.
  • Riwayat transaksi. Pesanan, invoice, atau tiket dukungan mungkin perlu tetap tersedia untuk pemeriksaan.
  • Relasi antar-data. Menghapus pengguna secara permanen dapat menimbulkan masalah pada data lain yang masih merujuk kepadanya.
  • Kebutuhan audit. Tim dapat mengetahui kapan sebuah data dinonaktifkan, terutama jika ditambah kolom deleted_by.

Namun, soft delete bukan berarti database menjadi aman secara otomatis. Data yang ditandai terhapus tetap harus dilindungi, dan aturan aksesnya tetap perlu dibuat dengan hati-hati.

Kesalahan paling umum: lupa menyaring data

Masalah klasik soft delete terjadi ketika satu query lupa menambahkan WHERE deleted_at IS NULL. Akibatnya, data yang seharusnya sudah tidak aktif muncul kembali di halaman pengguna, laporan, atau hasil pencarian.

Kesalahan ini sering terjadi karena filter ditulis berulang kali di banyak tempat. Salah satu cara menguranginya adalah membuat fungsi atau lapisan akses data yang selalu menerapkan filter default.

Contoh sederhana dalam PHP menggunakan PDO:

$sql = 'SELECT id, name, email
FROM users
WHERE deleted_at IS NULL
ORDER BY name ASC';

$statement = $pdo->prepare($sql);
$statement->execute();
$users = $statement->fetchAll(PDO::FETCH_ASSOC);

Untuk aplikasi yang lebih besar, pola ini bisa ditempatkan di repository, model, atau query builder. Tujuannya bukan sekadar mengurangi penulisan kode, tetapi mencegah satu endpoint menampilkan data yang seharusnya tersembunyi.

Bedakan data aktif, terhapus, dan dihapus permanen

Jangan menganggap soft delete hanya memiliki dua keadaan: ada dan tidak ada. Dalam aplikasi nyata, biasanya ada setidaknya tiga kondisi:

  1. Aktif: dapat digunakan dalam proses normal.
  2. Dihapus sementara: tidak muncul di tampilan umum, tetapi masih dapat dipulihkan.
  3. Dihapus permanen: benar-benar dibuang setelah melewati aturan tertentu.

Perbedaan ini penting untuk merancang halaman admin. Pengguna biasa mungkin hanya melihat data aktif, sedangkan admin dapat melihat tempat sampah atau arsip. Data yang berada di tempat sampah juga sebaiknya memiliki batas waktu, misalnya dihapus permanen setelah melewati masa retensi yang telah ditentukan bisnis.

Gunakan deleted_at, bukan hanya is_deleted

Kolom boolean seperti is_deleted memang mudah dipahami, tetapi informasinya terbatas. Nilai TRUE hanya memberi tahu bahwa data sudah ditandai. Kita tidak tahu kapan perubahan itu terjadi.

Kolom deleted_at menyimpan waktu penghapusan dan lebih berguna untuk audit, pemulihan, serta pekerjaan pembersihan data. Jika dibutuhkan, tambahkan pula:

  • deleted_by untuk menyimpan identitas pengguna yang melakukan tindakan.
  • delete_reason untuk mencatat alasan penghapusan.
  • restored_at untuk mencatat kapan data dipulihkan.
  • restored_by untuk mencatat siapa yang memulihkan data.

Tidak semua aplikasi memerlukan seluruh kolom tersebut. Pilih berdasarkan kebutuhan audit dan risiko bisnis, bukan sekadar menambah kolom sebanyak mungkin.

Perhatikan relasi dan data unik

Soft delete menjadi lebih rumit ketika tabel memiliki relasi. Misalnya, sebuah alamat pelanggan ditandai terhapus, tetapi pesanan lama masih menggunakannya. Apakah alamat itu boleh dihapus dari tampilan admin? Apakah pesanan harus tetap menampilkan alamat lama?

Jawabannya bergantung pada konteks. Data transaksi biasanya perlu mempertahankan kondisi historisnya. Karena itu, jangan selalu mengambil data relasi dengan filter aktif secara membabi buta. Untuk invoice atau pesanan lama, informasi yang sudah menjadi bagian dari transaksi mungkin perlu disalin sebagai snapshot.

Masalah lain muncul pada kolom unik, seperti email. Jika pengguna dengan email tertentu dihapus sementara, apakah pengguna baru boleh memakai email yang sama? MySQL tidak otomatis memahami aturan bisnis tersebut. Tim perlu menentukan apakah email pada data terhapus tetap dianggap terpakai atau boleh digunakan kembali.

Yang bisa dilakukan sekarang

  1. Tentukan tabel mana yang benar-benar membutuhkan pemulihan atau audit.
  2. Gunakan deleted_at DATETIME NULL sebagai penanda utama.
  3. Buat aturan query default agar data terhapus tidak ikut tampil.
  4. Sediakan halaman admin untuk melihat dan memulihkan data terhapus jika diperlukan.
  5. Tentukan kapan data boleh dihapus permanen.
  6. Uji relasi, pencarian, laporan, dan validasi data unik setelah soft delete diterapkan.

Soft delete bukan pengganti kebijakan data

Soft delete berguna ketika aplikasi perlu menjaga jejak dan memberi kesempatan untuk memulihkan kesalahan. Tetapi menyimpan semua data selamanya juga bukan strategi yang baik. Database bisa membesar, pencarian menjadi kurang efisien, dan data lama mungkin tidak lagi perlu disimpan.

Pendekatan yang sehat adalah menggabungkan soft delete dengan kebijakan retensi, kontrol akses, backup, dan proses penghapusan permanen yang terukur. Dengan begitu, tombol hapus tidak hanya bekerja secara teknis, tetapi juga sesuai dengan kebutuhan operasional aplikasi.

– Rio Yotto @rioyotto