Bagaimana Anda mengelola basis data dalam pengembangan, pengujian, dan produksi?

171

Saya kesulitan mencari contoh yang baik tentang cara mengelola skema basis data dan data antara server pengembangan, pengujian, dan produksi.

Inilah pengaturan kami. Setiap pengembang memiliki mesin virtual yang menjalankan aplikasi kami dan database MySQL. Ini adalah kotak pasir pribadi mereka untuk melakukan apa pun yang mereka inginkan. Saat ini, pengembang akan membuat perubahan pada skema SQL dan melakukan dump database ke file teks yang mereka komit ke dalam SVN.

Kami ingin menggunakan server pengembangan integrasi berkelanjutan yang akan selalu menjalankan kode terbaru. Jika kita melakukannya sekarang, itu akan memuat ulang database dari SVN untuk setiap build.

Kami memiliki server uji (virtual) yang menjalankan "rilis kandidat." Menyebarkan ke server uji saat ini adalah proses yang sangat manual, dan biasanya melibatkan saya memuat SQL terbaru dari SVN dan mengubahnya. Juga, data pada server uji tidak konsisten. Anda berakhir dengan data uji apa pun yang dilakukan pengembang terakhir di server sandbox-nya.

Di mana semuanya rusak adalah penyebaran produksi. Karena kami tidak dapat menimpa data langsung dengan data uji, ini melibatkan pembuatan ulang secara manual semua perubahan skema. Jika ada banyak perubahan skema atau skrip konversi untuk memanipulasi data, ini bisa menjadi sangat berbulu.

Jika masalahnya hanya skema, itu akan menjadi masalah yang lebih mudah, tetapi ada "basis" data dalam database yang diperbarui selama pengembangan juga, seperti meta-data dalam tabel keamanan dan izin.

Ini adalah penghalang terbesar yang saya lihat dalam bergerak menuju integrasi berkelanjutan dan pembangunan satu langkah. Bagaimana Anda mengatasinya?


Pertanyaan tindak lanjut: bagaimana Anda melacak versi database sehingga Anda tahu skrip mana yang harus dijalankan untuk memutakhirkan instance database yang diberikan? Apakah tabel versi seperti Lance menyebutkan di bawah prosedur standar?


Terima kasih untuk referensi ke Tarantino. Saya tidak berada dalam lingkungan .NET, tetapi saya menemukan halaman wiki DataBaseChangeMangement mereka sangat membantu. Terutama Presentasi Powerpoint ini (.ppt)

Saya akan menulis skrip Python yang memeriksa nama *.sqlskrip dalam direktori yang diberikan terhadap tabel dalam database dan menjalankan skrip yang tidak ada di sana berdasarkan pada bilangan bulat yang membentuk bagian pertama dari nama file. Jika ini adalah solusi yang cukup sederhana, seperti yang saya duga, maka saya akan mempostingnya di sini.


Saya punya skrip yang berfungsi untuk ini. Ini menangani inisialisasi DB jika tidak ada dan menjalankan skrip upgrade seperlunya. Ada juga sakelar untuk menghapus database yang ada dan mengimpor data uji dari file. Itu sekitar 200 baris, jadi saya tidak akan mempostingnya (meskipun saya mungkin meletakkannya di pastebin jika ada minat).

Matt Miller
sumber
"Saya akan menulis skrip Python yang memeriksa nama skrip * .sql di direktori yang diberikan terhadap tabel dalam database dan menjalankan yang tidak ada di sana berdasarkan pada bilangan bulat yang membentuk bagian pertama dari nama file. Jika ini adalah solusi yang cukup sederhana, seperti yang saya duga, maka saya akan mempostingnya di sini. " Sepertinya Anda menerapkan jalur terbang.
masterxilo

Jawaban:

53

Ada beberapa pilihan bagus. Saya tidak akan menggunakan strategi "mengembalikan cadangan".

  1. Script semua perubahan skema Anda, dan minta server CI Anda menjalankan skrip-skrip tersebut pada database. Memiliki tabel versi untuk melacak versi database saat ini, dan hanya menjalankan skrip jika mereka untuk versi yang lebih baru.

  2. Gunakan solusi migrasi. Solusi ini bervariasi menurut bahasa, tetapi untuk .NET saya menggunakan Migrator.NET. Ini memungkinkan Anda untuk membuat versi basis data dan bergerak naik turun antar versi. Skema Anda ditentukan dalam kode C #.

Lance Fisher
sumber
28

Pengembang Anda perlu menulis skrip perubahan (skema dan perubahan data) untuk setiap bug / fitur yang mereka kerjakan, tidak hanya sekadar membuang seluruh database ke dalam kontrol sumber. Skrip ini akan meningkatkan basis data produksi saat ini ke versi baru dalam pengembangan.

Proses build Anda dapat mengembalikan salinan database produksi ke lingkungan yang sesuai dan menjalankan semua skrip dari kontrol sumber di atasnya, yang akan memperbarui database ke versi saat ini. Kami melakukan ini setiap hari untuk memastikan semua skrip berjalan dengan benar.

tffffni
sumber
13

Lihat bagaimana Ruby on Rails melakukan ini.

Pertama ada yang disebut file migrasi, yang pada dasarnya mengubah skema basis data dan data dari versi N ke versi N + 1 (atau dalam kasus penurunan versi dari versi N + 1 ke N). Database memiliki tabel yang memberitahukan versi saat ini.

Database uji selalu dihapus sebelum unit-tes dan diisi dengan data tetap dari file.

Juha Syrjälä
sumber
10

Buku Refactoring Databases: Evolutionary Database Design mungkin memberi Anda beberapa ide tentang cara mengelola database. Versi singkat juga dapat dibaca di http://martinfowler.com/articles/evodb.html

Dalam satu proyek PHP + MySQL, saya sudah memiliki nomor revisi database yang disimpan dalam database, dan ketika program terhubung ke database, pertama-tama akan memeriksa revisi. Jika program memerlukan revisi yang berbeda, itu akan membuka halaman untuk meningkatkan basis data. Setiap pemutakhiran ditentukan dalam kode PHP, yang akan mengubah skema basis data dan memigrasi semua data yang ada.

Esko Luontola
sumber
5
  • Beri nama basis data Anda sebagai berikut - dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>(Tentunya Anda tidak harus menggunakan nama db hardcode
  • Dengan demikian Anda akan dapat menyebarkan bahkan berbagai jenis db pada server fisik yang sama (saya tidak merekomendasikan itu, tetapi Anda mungkin harus ... jika sumber daya yang ada sangat terbatas)
  • Pastikan Anda dapat memindahkan data di antara mereka secara otomatis
  • Pisahkan skrip pembuatan db dari populasi = Harus selalu memungkinkan untuk membuat ulang db dari awal dan mengisinya (dari versi db lama atau sumber data eksternal)
  • jangan gunakan string koneksi hardcode dalam kode (bahkan tidak dalam file config) - gunakan dalam template string koneksi file config, yang Anda isi secara dinamis, setiap konfigurasi ulang dari application_layer yang perlu dikompilasi ulang adalah BAD
  • gunakan versi database dan objek db versi - jika Anda mampu menggunakan produk siap, jika tidak mengembangkan sesuatu sendiri
  • lacak setiap perubahan DDL dan simpan ke dalam tabel sejarah ( contoh di sini )
  • Backup SETIAP HARI! Uji seberapa cepat Anda dapat memulihkan sesuatu yang hilang dari cadangan (gunakan skrip pemulihan otomatis)
  • bahkan basis data DEV Anda dan PROD memiliki skrip kreasi yang sama persis Anda akan mengalami masalah dengan data, jadi izinkan pengembang untuk membuat salinan yang tepat dari prod dan bermain dengannya (saya tahu saya akan menerima minus untuk yang satu ini, tetapi perubahan dalam pola pikir dan proses bisnis akan dikenakan biaya lebih sedikit ketika kotoran mengenai penggemar - jadi paksa coders untuk mensubkripsikan apa pun yang dibuat secara legal, tetapi pastikan yang ini
Yordan Georgiev
sumber
Poin terakhir adalah mood. Jika perlu, itu menunjukkan definisi proyek rusak. Pengembangan harus mengarah sebelum produksi. Jika data produksi menginduksi efek samping, itu menunjukkan masalah yang lebih besar. Bersihkan data produksi. Juga jelaskan langkah terakhir dengan petugas perlindungan data, jika ada alasan - seperti yang Anda sarankan - bahwa data langsung harus ada pada sistem pengembangan, periksa apakah ini berlaku secara hukum. Salinan yang tepat dari data produksi memperlambat pengembangan dan integrasi sebagian besar. Pertimbangkan proses yang lebih murah jika Anda tidak mampu membeli barang mewah seperti itu.
hakre
Masalahnya adalah bahwa selama pengembangan bahkan tidak mungkin untuk membayangkan semua kasus sudut dalam aliran kontrol dan variasi dalam kualitas data yang akan terjadi dalam produksi. Jika Anda berada di perusahaan besar, untuk memiliki masalah hukum untuk itu maka beberapa jenis pengacakan data dan / atau solusi masking harus diimplementasikan, yang menambah lapisan kompleksitas tambahan, tetapi masih harus mempertahankan aspek kualitas data yang menyebabkan bug. pertama-tama ...
Yordan Georgiev
4

Ini adalah sesuatu yang saya selalu tidak puas dengan - solusi kami untuk masalah ini. Selama beberapa tahun kami mempertahankan skrip perubahan terpisah untuk setiap rilis. Script ini akan berisi delta dari rilis produksi terakhir. Dengan setiap rilis aplikasi, nomor versi akan bertambah, memberikan sesuatu seperti berikut:

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

Ini bekerja dengan cukup baik sampai kami mulai mempertahankan dua jalur pengembangan: Trunk / Mainline untuk pengembangan baru, dan cabang pemeliharaan untuk perbaikan bug, peningkatan jangka pendek, dll. Tidak dapat dihindari, kebutuhan muncul untuk membuat perubahan pada skema di cabang. Pada titik ini, kami sudah memiliki dbChanges_n + 1.sql di Trunk, jadi kami akhirnya membuat skema seperti berikut:

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

Sekali lagi, ini bekerja dengan cukup baik, sampai suatu hari kami melihat ke atas dan melihat 42 skrip delta di jalur utama dan 10 di cabang. ARGH!

Saat ini kami hanya memelihara satu skrip delta dan membiarkan versi SVN - yaitu kami menimpa skrip dengan setiap rilis. Dan kami menghindar dari membuat perubahan skema di cabang.

Jadi, saya juga tidak puas dengan ini. Saya sangat menyukai konsep migrasi dari Rails. Saya menjadi sangat terpesona dengan LiquiBase . Ini mendukung konsep refactorings basis data tambahan. Ini layak untuk dilihat dan saya akan segera memeriksanya. Adakah yang punya pengalaman dengan itu? Saya sangat ingin tahu tentang hasil Anda.

Matt Stine
sumber
4

Anda juga bisa melihat menggunakan alat seperti SQL Bandingkan untuk skrip perbedaan antara berbagai versi database, memungkinkan Anda untuk bermigrasi dengan cepat antar versi

Rad
sumber
3

Kami memiliki pengaturan yang sangat mirip dengan OP.

Pengembang berkembang di VM dengan DB pribadi.

[Pengembang akan segera berkomitmen ke cabang pribadi]

Pengujian dijalankan pada mesin yang berbeda (sebenarnya di dalam VM yang dihosting di server) [Akan segera dijalankan oleh server Hudson CI]

Tes dengan memuat referensi dump ke db. Terapkan tambalan skema pengembang lalu terapkan tambalan data pengembang

Kemudian jalankan pengujian unit dan sistem.

Produksi dikerahkan ke pelanggan sebagai installer.

Apa yang kita lakukan:

Kami mengambil skema pembuangan DB kotak pasir kami. Kemudian dump data sql. Kami berbeda dengan baseline sebelumnya. sepasang delta itu adalah untuk meningkatkan n-1 ke n.

kami mengkonfigurasi dumps dan delta.

Jadi untuk menginstal versi N CLEAN kita jalankan dump ke db kosong. Untuk menambal, terapkan tambalan yang mengintervensi.

(Juha menyebutkan ide Rail memiliki tabel yang merekam versi DB saat ini adalah ide yang bagus dan harus membuat menginstal pembaruan menjadi lebih mudah.)

Delta dan dump harus ditinjau sebelum pengujian beta. Saya tidak bisa melihat jalan keluar karena saya melihat pengembang memasukkan akun uji ke dalam DB sendiri.

Tim Williscroft
sumber
3

Saya khawatir saya setuju dengan poster lain. Pengembang perlu membuat skrip perubahan mereka.

Dalam banyak kasus, ALTER TABLE sederhana tidak akan berfungsi, Anda perlu memodifikasi data yang ada juga - pengembang perlu memikirkan migrasi apa yang diperlukan dan memastikan mereka ditulis dengan benar (tentu saja Anda perlu menguji ini dengan hati-hati di beberapa titik di siklus rilis).

Selain itu, jika Anda memiliki akal, Anda akan mendapatkan pengembang Anda untuk mengembalikan script script untuk perubahan mereka juga sehingga mereka dapat dikembalikan jika perlu. Ini harus diuji juga, untuk memastikan bahwa kemunduran mereka tidak hanya dieksekusi tanpa kesalahan, tetapi membuat DB dalam keadaan yang sama seperti sebelumnya (ini tidak selalu mungkin atau diinginkan, tetapi merupakan aturan yang baik sebagian besar waktu) .

Bagaimana Anda menghubungkannya ke server CI, saya tidak tahu. Mungkin server CI Anda perlu memiliki snapshot build yang sudah dikenal, yang dikembalikan ke setiap malam dan kemudian menerapkan semua perubahan sejak saat itu. Itu mungkin yang terbaik, jika tidak, skrip migrasi yang rusak tidak hanya akan merusak bangunan malam itu, tetapi juga semua yang berikutnya.

MarkR
sumber
1

Lihat dbdeploy , ada alat Java dan .net sudah tersedia, Anda bisa mengikuti standar mereka untuk tata letak file SQL dan tabel versi skema dan menulis versi python Anda.

Dave Marshall
sumber
1

Kami menggunakan command-line mysql-diff : ini menghasilkan perbedaan antara dua skema database (dari live DB atau skrip) sebagai skrip ALTER. mysql-diff dieksekusi pada awal aplikasi, dan jika skema berubah, ia melapor kepada pengembang. Jadi pengembang tidak perlu menulis ALTER secara manual, pembaruan skema terjadi secara semi-otomatis.

stepancheg
sumber
0

Saya telah menulis alat yang (dengan menghubungkan ke Open DBDiff ) membandingkan skema database, dan akan menyarankan skrip migrasi kepada Anda. Jika Anda membuat perubahan yang menghapus atau memodifikasi data, itu akan menimbulkan kesalahan, tetapi memberikan saran untuk skrip (misalnya ketika kolom yang hilang dalam skema baru, itu akan memeriksa apakah kolom telah diganti nama dan membuat xx - dihasilkan script.sql.saransi berisi pernyataan ganti nama).

http://code.google.com/p/migrationscriptgenerator/ SQL Server saja, saya khawatir :( Ini juga sangat alfa, tapi itu SANGAT gesekan rendah (terutama jika Anda menggabungkannya dengan Tarantino atau http://code.google .com / p / simplescriptrunner / )

Cara saya menggunakannya adalah memiliki proyek skrip SQL di .sln Anda. Anda juga memiliki basis data db_next di tempat Anda membuat perubahan (menggunakan Management Studio atau Ekspor Skema NHibernate atau LinqToSql CreateDatabase atau sesuatu). Kemudian Anda menjalankan migrationscriptgenerator dengan DB _dev dan _next, yang membuat. skrip pembaruan SQL untuk dimigrasi ke seberang.

mcintyre321
sumber
0

Untuk database oracle kami menggunakan alat oracle-ddl2svn .

Alat ini mengotomatiskan proses selanjutnya

  1. untuk setiap skema db, dapatkan skema ddls
  2. letakkan di bawah versi contol

perubahan antara instance diselesaikan secara manual

popalka
sumber