Banyak artikel telah ditulis tentang memperbarui sistem dengan cepat tanpa menghentikannya (penerapan zero-downtime) dan banyak aspek dari pendekatan ini cukup jelas. Menurut pendapat saya, bagian paling sulit dari penyebaran dalam hal ini adalah memperbarui gudang data jika kontrak (skema) mereka telah berubah. Aspek inilah yang ingin saya pertimbangkan dalam artikel ini.
Apa pun basis data - dengan skema data eksplisit sebagai relasional atau dengan yang sewenang-wenang sebagai NoSQL - skema data masih ada, bahkan di tingkat aplikasi. Data yang dibaca dari database harus dapat dimengerti oleh klien, bahkan jika repositori itu sendiri tidak memaksakan batasan pada struktur mereka.
Misalkan suatu sistem dengan struktur data tertentu dan terabyte data dalam database sudah berjalan dalam produksi. Dalam versi baru sistem, kita perlu sedikit mengubah struktur untuk mengimplementasikan fitur baru atau meningkatkan kinerja. Pertimbangkan perubahan apa yang mungkin terjadi pada rangkaian:
- Menambahkan Bidang Baru
- Penghapusan bidang
- Ganti nama Bidang
- Perubahan Jenis Bidang
- Mentransfer bidang ke struktur data lain (misalnya, dalam kasus denormalisasi)
Menambahkan bidang baru serta menambahkan objek basis data lainnya adalah perubahan yang kompatibel ke belakang dan tidak memerlukan langkah-langkah tambahan dalam hal menerapkan penerapan zero-downtime (dengan satu peringatan - jika bidang atau objek baru ini tidak bergantung secara fungsional pada yang lain yang telah disimpan dalam database. data). Cukup menerapkan perubahan ke database dengan cepat, dan kemudian menggunakan versi baru dari kode yang menggunakan objek database baru.
Menghapus bidang atau objek basis data lain bukanlah perubahan yang kompatibel ke belakang, tetapi pendekatan untuk penerapannya sangat sederhana - objek basis data yang tidak perlu harus dihapus hanya setelah versi baru sistem benar-benar menemui jalan buntu.
Tiga jenis perubahan lainnya lebih kompleks dalam hal penyediaan penerapan zero-downtime. Secara umum, semuanya dapat dilakukan dengan menyalin data ke bidang / entitas lain, dan menghapus yang "lama" setelah migrasi data berhasil: untuk mengganti nama, Anda dapat menyalin data dari bidang lama ke bidang dengan nama baru, lalu hapus bidang lama, ubah jenis data dapat dilakukan bersamaan dengan penggantian nama, dll. Dengan satu atau lain cara, selama periode waktu tertentu, basis data harus mendukung kontrak lama dan baru. Setidaknya ada dua cara untuk melakukan perubahan tersebut dengan cepat:
Jika database mendukung pemicu
- Buat pemicu yang menyalin data dari tempat lama ke yang baru pada setiap perubahan / penambahan dan setel pada produksi.
- Terapkan utilitas konversi data yang melakukan hal yang sama, tetapi untuk semua catatan dalam database. Karena pemicu sudah diinstal, utilitas mungkin tidak melakukan hal yang lebih rumit dari sekadar pembaruan "fiktif" dari setiap catatan (tabel SET UPDATE bidang = bidang ...). Poin yang sangat penting di sini adalah bahwa tindakan membaca data dari tempat lama dan menulis ke yang baru harus bersifat atomik dan dilindungi dari perubahan yang hilang. Bergantung pada struktur database, Anda dapat menggunakan penguncian pesimistis melalui SELECT FOR UPDATE atau analognya, atau optimis jika tabel memiliki bidang dengan versi rekaman.
- Setelah utilitas menyelesaikan tugasnya (tergantung pada jumlah data dan kerumitan pembaruan, waktu eksekusi dapat memakan waktu berhari-hari), sudah dimungkinkan untuk menginstal versi baru dari sistem yang mendukung skema data baru. Pada titik ini, semua catatan dalam database yang ada pada saat utilitas diluncurkan akan berhasil dikonversi, dan semua yang baru yang muncul selama operasinya juga akan dikonversi oleh pemicu.
- Hapus pemicu dan semua bidang (atau objek basis data lainnya) yang tidak lagi diperlukan.
Jika tidak mungkin menggunakan pemicu (seperti halnya dengan banyak solusi NoSQL)

- Membuat dan menggunakan versi baru aplikasi (versi sementara 1 dalam gambar), yang selalu membaca dari bidang yang lama, tetapi ketika menulis ke bidang ini, ia memperbarui tempat lama dan baru yang sesuai (pada gambar "C" - yang lama, "H" - baru). Zadeplit versi ini ke semua node yang menjalankan instance aplikasi.
- Terapkan utilitas yang menyalin data dari lokasi lama ke yang baru. Seperti halnya pemicu, Anda perlu mengambil langkah-langkah untuk mencegah perubahan yang hilang.
- Buat dan, setelah selesai utilitas, instal versi lain dari aplikasi (versi sementara 2), yang membaca data dari bidang baru, tetapi masih menulis di dua tempat. Langkah ini diperlukan, karena selama pembaruan berurutan dari masing-masing node masih akan ada kesenjangan ketika instance dari versi sebelumnya dari aplikasi yang membaca bidang lama bekerja secara bersamaan dengan yang baru.
- Buat dan di akhir sapuan penuh versi sebelumnya gunakan versi final, yang sudah tidak berinteraksi dengan bidang lama.
- Hapus bidang yang lama.
Pendekatan kedua membutuhkan pembuatan dan pemasangan tiga versi aplikasi yang berbeda, yang bisa sangat merepotkan dan tidak praktis. Sebagai gantinya, Anda dapat menggunakan fitur toggling - untuk menempatkan logika ketiga versi menjadi satu, tetapi alihkan modenya tergantung pada parameter konfigurasi, yang idealnya dapat diaktifkan dengan cepat. Jadi, daripada menginstal setiap versi berikutnya, itu akan cukup untuk mengubah nilai parameter (dan memulai kembali layanan jika memperbarui konfigurasi dengan cepat tidak disediakan). Setelah berhasil menyelesaikan instalasi versi final, semua kode yang terkait dengan memastikan migrasi data harus sepenuhnya dihapus dari cabang kerja, bahkan jika itu akan "hidup" pada produksi sampai pembaruan sistem berikutnya.
Sangat mudah untuk memperhatikan bahwa memastikan zero downtime ketika memperbarui sistem adalah prosedur yang rumit dan rapuh, jadi masuk akal untuk repot hanya jika ada persyaratan yang sesuai dari bisnis. Tetapi bahkan jika persyaratan untuk ketersediaan sistem cukup rendah (misalnya, 99% per tahun dan jendela untuk pembaruan sistem yang direncanakan adalah 24 jam), konversi data yang diperlukan untuk menginstal versi baru mungkin masih membutuhkan waktu lebih lama. Karena itu, Anda harus siap terlebih dahulu untuk penggunaan solusi tersebut jika Anda berencana untuk menyimpan data dalam jumlah besar.
Pendekatan alternatif mungkin adalah penolakan yang disengaja terhadap perubahan yang tidak kompatibel ke belakang dalam skema database, tetapi, sayangnya, dalam praktiknya hal itu tidak selalu dapat dicapai, karena seringkali cara paling efektif untuk meningkatkan kinerja akses data adalah merestrukturisasi skema tersebut.