Bagaimana cara menjalankan migrasi basis data dengan banyak instance aplikasi?

10

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, node1mulai, kemudian mulai menjalankan migrasi. Sekarang, node4mulai, dan migrasi yang sudah berjalan lama belum selesai, begitu node4juga 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 etcdatau 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.

Ben
sumber
1
Bagaimana dengan menggunakan tabel "status migrasi" sebagai kunci global / terdistribusi Anda? Baris tunggal akan menunjukkan apakah migrasi saat ini aktif dan mungkin migrasi apa yang dilakukan terakhir kali.
Bart van Ingen Schenau
Apakah Anda perlu menggunakan aplikasi secara tidak sinkron?
Ben

Jawaban:

4

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 migrationstabel 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):

  • Mulai transaksi
  • SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
  • jika pernyataan sebelumnya mengembalikan nilai, akhiri transaksi
  • terapkan migrasi (gulung balik jika gagal, catat kegagalan dan akhiri transaksi)
  • INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
  • akhiri transaksi

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.

Doc Brown
sumber
1

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:

  • Liquibase : Dari FAQ mereka : Liquibase menggunakan sistem penguncian terdistribusi untuk hanya memungkinkan satu proses untuk memperbarui database pada suatu waktu. Proses lain hanya akan menunggu sampai kunci dilepaskan.
  • Jalur terbang : Dari halaman pengunduhan mereka : Aman untuk beberapa node secara paralel ✓

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.

siegi
sumber