Kami memiliki aplikasi yang memiliki campuran migrasi cepat (<1 detik) dan database lambat (> 30 detik). Saat ini, kami menjalankan migrasi basis data sebagai bagian dari CI, tetapi kemudian alat CI kami harus mengetahui semua rangkaian koneksi basis data untuk aplikasi kami (lintas beberapa lingkungan) yang tidak ideal. Kami ingin mengubah proses ini sehingga aplikasi menjalankan migrasi basis datanya sendiri ketika dijalankan.
Inilah situasinya:
Kami memiliki beberapa contoh aplikasi ini - sekitar 5 dalam produksi. Sebut saja mereka node1, ..., node5
. Setiap aplikasi terhubung ke turunan SQL Server tunggal, dan kami tidak menggunakan penyebaran bergulir (semua aplikasi dikerahkan secara bersamaan sejauh yang saya tahu)
Masalah: misalkan kita memiliki migrasi yang berjalan lama. Dalam hal ini, node1
mulai, kemudian mulai menjalankan migrasi. Sekarang, node4
mulai, dan migrasi yang sudah berjalan lama belum selesai, begitu node4
juga mulai menjalankan migrasi -> kemungkinan korupsi data? Bagaimana Anda mencegah masalah ini atau apakah masalah itu cukup penting untuk dikhawatirkan?
Saya sedang berpikir untuk menyelesaikan masalah ini dengan kunci terdistribusi (menggunakan etcd
atau sesuatu di sepanjang garis itu). Pada dasarnya, semua aplikasi mencoba untuk mendapatkan kunci, hanya satu dari mereka yang mendapatkannya dan menjalankan migrasi, lalu membuka kunci. Ketika sisa aplikasi mulai dan masuk ke bagian kritis, semua migrasi sudah dijalankan sehingga skrip migrasi keluar begitu saja.
Namun, nyali saya mengatakan "ini berlebihan, pasti ada solusi yang lebih sederhana," jadi saya pikir saya akan bertanya di sini untuk melihat apakah ada orang lain yang memiliki ide yang lebih baik.
Jawaban:
Karena Anda menyebutkan SQL server: menurut posting DBA.SE ini sebelumnya , perubahan skema dapat (dan harus) dimasukkan ke dalam transaksi. Ini memberi Anda kemampuan untuk mendesain migrasi Anda sama seperti bentuk penulisan bersamaan lainnya ke DB - Anda memulai transaksi, dan ketika gagal, Anda mengembalikannya. Itu mencegah setidaknya beberapa skenario korupsi basis data terburuk (meskipun transaksi saja tidak akan mencegah hilangnya data ketika ada langkah migrasi destruktif seperti menghapus kolom atau tabel).
Sejauh ini, saya yakin Anda juga akan memerlukan beberapa
migrations
tabel tempat migrasi yang sudah terdaftar terdaftar, sehingga proses aplikasi dapat memeriksa apakah migrasi tertentu sudah diterapkan atau belum. Kemudian gunakan "SELECT FOR UPDATE" untuk mengimplementasikan migrasi Anda seperti ini (kode semu):SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
Itu membangun mekanisme penguncian langsung ke tes "adalah migrasi sudah diterapkan" .
Perhatikan bahwa desain ini akan - secara teori - memungkinkan langkah-langkah migrasi Anda tidak mengetahui aplikasi mana yang benar-benar menerapkannya - bisa saja langkah 1 diterapkan oleh app1, langkah 2 oleh app2, langkah 3 oleh app 3, langkah 4 oleh app1 lagi, dan seterusnya. Namun, ada baiknya juga untuk tidak menerapkan migrasi selama instans aplikasi lain sedang digunakan. Penempatan paralel, sebagaimana disebutkan dalam pertanyaan Anda, mungkin sudah memperhatikan kendala ini.
sumber
Mungkin Anda dapat menemukan perpustakaan yang mendukung migrasi database dengan banyak node.
Saya tahu tentang dua perpustakaan di dunia Java, keduanya mendukung apa yang Anda butuhkan:
Mungkin ada alat lain untuk Java dan bahasa lain juga.
Jika Anda tidak dapat (atau tidak ingin) menggunakan alat seperti itu, sebuah tabel dapat digunakan sebagai kunci atau bahkan sebagai log migrasi, lihat Doc Browns menjawab sebagai contoh.
sumber