Mengapa Anda Harus Selalu Dry-Run Migrasi Database Sebelum Menyentuh Data Nyata

Anda telah menulis skrip migrasi. Tampaknya benar. Logikanya masuk akal. Anda menjalankannya di staging, dan semuanya berhasil. Namun saat dijalankan di produksi, terjadi masalah. Mungkin constraint kolom gagal. Mungkin muncul pelanggaran foreign key. Mungkin migrasi memakan waktu 45 menit, bukan 5 menit seperti yang diperkirakan, mengunci tabel kritis dan menyebabkan rentetan timeout di seluruh aplikasi Anda.

Skenario ini umum terjadi. Dan ini bisa dicegah. Tekniknya sederhana: lakukan dry-run pada migrasi Anda sebelum benar-benar menyentuh data nyata.

Apa yang Sebenarnya Dilakukan Dry-Run

Dry-run persis seperti namanya. Anda menjalankan skrip migrasi, tetapi Anda tidak pernah melakukan commit perubahan. Tidak ada tabel yang diubah. Tidak ada baris yang dipindahkan. Tidak ada kolom yang dihapus. Anda hanya memeriksa apakah skrip berjalan tanpa error, dan jika ada masalah, Anda mengetahuinya sebelum data terpengaruh.

Cara paling umum untuk melakukannya adalah dengan membungkus migrasi Anda di dalam transaksi database dan mengakhirinya dengan ROLLBACK, bukan COMMIT. Jika Anda memiliki skrip yang menambahkan kolom baru dan mengisinya dari tabel lain, bungkus semuanya dalam BEGIN TRANSACTION ... ROLLBACK. Jika terjadi error di tengah jalan, transaksi otomatis dibatalkan dan database kembali ke keadaan semula. Jika tidak ada error, Anda tetap melakukan rollback secara manual. Anda tidak bertujuan untuk menerapkan perubahan. Anda mencari konfirmasi bahwa skrip tersebut valid.

Berikut contoh konkret dalam SQL:

BEGIN TRANSACTION;

-- Contoh migrasi: menambahkan kolom baru dan mengisinya
ALTER TABLE users ADD COLUMN last_login_at TIMESTAMP;

UPDATE users
SET last_login_at = NOW()
WHERE last_login_at IS NULL;

-- Verifikasi data terlihat benar sebelum rollback
SELECT id, email, last_login_at FROM users LIMIT 10;

-- Rollback transaksi, biarkan database tidak berubah
ROLLBACK;

Informasi Lebih dari Sekadar Error Sintaks yang Didapat dari Dry-Run

Memeriksa error sintaks atau pelanggaran constraint adalah manfaat yang jelas. Namun dry-run memberi Anda informasi yang jauh lebih berguna.

Anda bisa melihat berapa lama migrasi akan berlangsung. Anda bisa melihat berapa banyak baris yang akan terpengaruh. Anda bisa melihat apakah migrasi akan mengunci tabel dan berapa lama. Ini adalah informasi kritis, terutama jika migrasi Anda menargetkan database produksi yang menangani ribuan permintaan per detik. Jika dry-run Anda menunjukkan migrasi akan memakan waktu 30 menit dan selama itu tabel utama akan terkunci, Anda tahu Anda memerlukan strategi berbeda. Mungkin Anda menjalankan migrasi di luar jam sibuk. Mungkin Anda menggunakan teknik migrasi online yang menghindari penguncian lama. Mungkin Anda memecah migrasi menjadi batch yang lebih kecil.

Tanpa dry-run, Anda hanya menebak. Dengan dry-run, Anda memiliki data untuk membuat keputusan yang tepat.

Tempat yang Tepat untuk Menjalankan Dry-Run

Tempat ideal adalah lingkungan staging dengan data yang sangat mirip dengan produksi. Namun tidak semua tim memiliki database staging dengan volume data yang realistis. Jika itu situasi Anda, ambil snapshot data produksi pada satu titik waktu dan muat ke database terpisah. Snapshot ini tidak boleh digunakan untuk transaksi nyata, tetapi cukup baik untuk menguji migrasi Anda.

Beberapa tim melangkah lebih jauh dengan mengotomatiskan dry-run. Setiap kali skrip migrasi berubah dalam pull request, job CI menjalankan dry-run secara otomatis. Ini menangkap masalah sebelum kode bahkan digabungkan. Ini adalah investasi kecil yang menghemat banyak waktu debugging di kemudian hari.

Cara Membaca Hasil Dry-Run

Output bersih tanpa error dan tanpa peringatan memang meyakinkan. Namun jangan berhenti di situ. Periksa log dengan saksama.

Cari baris yang gagal diisi karena data tidak cocok dengan tipe kolom baru. Cari konflik indeks. Cari pelanggaran foreign key. Terkadang dry-run berhasil secara teknis tetapi gagal secara logis. Misalnya, data yang Anda pindahkan mungkin kosong karena klausa WHERE Anda salah. Skrip berjalan dengan baik. Tidak ada error. Namun hasilnya tidak berguna.

Untuk menangkap ini, setelah dry-run selesai, jalankan query SELECT untuk memverifikasi isi tabel yang dimodifikasi seolah-olah migrasi benar-benar terjadi. Anda bisa melakukannya dalam transaksi yang sama sebelum melakukan rollback. Buka sesi terpisah, jalankan migrasi di dalam transaksi, dan sebelum rollback, query tabel yang dimodifikasi untuk memastikan data benar. Langkah tambahan ini mengubah dry-run dari sekadar pemeriksaan sintaks menjadi pemeriksaan logika.

Apa yang Tidak Dapat Dijamin oleh Dry-Run

Dry-run bukan jaminan bahwa migrasi akan berjalan mulus di produksi. Beberapa faktor tidak dapat direplikasi sepenuhnya. Beban query bersamaan akan berbeda. Volume data mungkin jauh lebih besar. Waktu penguncian mungkin bergeser. Namun dry-run mengurangi kejutan. Jika Anda telah menguji migrasi di lingkungan yang mendekati produksi dan hasilnya sesuai harapan, Anda dapat menjalankan migrasi nyata dengan keyakinan yang jauh lebih tinggi.

Daftar Periksa Praktis Sebelum Menjalankan Migrasi

Sebelum menjalankan migrasi apa pun yang menyentuh data produksi, lakukan daftar periksa singkat ini:

  • Bungkus migrasi dalam transaksi dan jalankan dengan ROLLBACK
  • Periksa waktu eksekusi dan durasi penguncian
  • Verifikasi jumlah baris yang terpengaruh sesuai harapan
  • Query tabel yang dimodifikasi dalam transaksi untuk memastikan kebenaran data
  • Tinjau log untuk pelanggaran constraint, konflik indeks, atau ketidakcocokan tipe
  • Jika migrasi terlalu lama atau terlalu berat dalam penguncian, rencanakan strategi alternatif

Intisari Konkret

Dry-run bukanlah langkah tambahan. Ini adalah langkah yang membedakan deployment yang percaya diri dari yang penuh tekanan. Jalankan migrasi Anda dalam transaksi. Rollback. Periksa hasilnya. Kemudian putuskan apakah Anda siap untuk melakukan commit. Data produksi Anda akan berterima kasih.