Mekanisme untuk melacak perubahan skema DB [ditutup]

135

Apa metode terbaik untuk melacak dan / atau mengotomatiskan perubahan skema DB? Tim kami menggunakan Subversion untuk kontrol versi dan kami telah dapat mengotomatiskan beberapa tugas kami dengan cara ini (mendorong pembangunan ke server pementasan, menerapkan kode yang diuji ke server produksi) tetapi kami masih melakukan pembaruan basis data secara manual. Saya ingin mencari atau membuat solusi yang memungkinkan kita untuk bekerja secara efisien di seluruh server dengan lingkungan yang berbeda sambil terus menggunakan Subversion sebagai backend di mana pembaruan kode dan DB didorong ke berbagai server.

Banyak paket perangkat lunak populer menyertakan skrip pembaruan otomatis yang mendeteksi versi DB dan menerapkan perubahan yang diperlukan. Apakah ini cara terbaik untuk melakukan ini bahkan dalam skala yang lebih besar (di banyak proyek dan terkadang banyak lingkungan dan bahasa)? Jika demikian, apakah ada kode yang ada di luar sana yang menyederhanakan proses atau lebih baik hanya menggunakan solusi kita sendiri? Adakah yang menerapkan sesuatu yang serupa sebelumnya dan mengintegrasikannya ke dalam hook pasca-commit Subversion, atau apakah ini ide yang buruk?

Meskipun solusi yang mendukung banyak platform lebih disukai, kami pasti perlu mendukung tumpukan Linux / Apache / MySQL / PHP karena sebagian besar pekerjaan kami ada di platform itu.

pix0r
sumber

Jawaban:

56

Di dunia Rails, terdapat konsep migrasi, skrip di mana perubahan pada database dibuat di Ruby, bukan di database khusus SQL. Kode migrasi Ruby Anda akhirnya diubah menjadi DDL khusus untuk database Anda saat ini; ini membuat peralihan platform database menjadi sangat mudah.

Untuk setiap perubahan yang Anda buat ke database, Anda menulis migrasi baru. Migrasi biasanya memiliki dua metode: metode "naik" tempat perubahan diterapkan dan metode "turun" di mana perubahan dibatalkan. Perintah tunggal membuat database diperbarui, dan juga dapat digunakan untuk membawa database ke versi skema tertentu. Di Rails, migrasi disimpan di direktorinya sendiri di direktori proyek dan diperiksa ke kontrol versi seperti kode proyek lainnya.

Panduan Oracle untuk migrasi Rails ini mencakup migrasi dengan cukup baik.

Pengembang yang menggunakan bahasa lain telah melihat migrasi dan telah menerapkan versi khusus bahasa mereka sendiri. Saya tahu tentang Ruckusing , sistem migrasi PHP yang dimodelkan setelah migrasi Rails; itu mungkin yang Anda cari.

Joey deVilla
sumber
1
Ruckusing FTW - kami mengadaptasikannya ke sistem db kami dan cukup puas dengannya.
Piskvor meninggalkan gedung
Sekarang ada di github: github.com/ruckus/ruckusing-migrations
50

Kami menggunakan sesuatu yang mirip dengan bcwoord untuk menjaga skema database kami tersinkronisasi di 5 instalasi yang berbeda (produksi, pementasan dan beberapa instalasi pengembangan), dan dicadangkan dalam kontrol versi, dan bekerja dengan cukup baik. Saya akan menjelaskan sedikit:


Untuk menyinkronkan struktur database, kami memiliki satu skrip, update.php, dan sejumlah file bernomor 1.sql, 2.sql, 3.sql, dll. Skrip ini menggunakan satu tabel tambahan untuk menyimpan nomor versi saat ini dari database. File N.sql dibuat dengan tangan, untuk beralih dari versi (N-1) ke versi N database.

Mereka dapat digunakan untuk menambahkan tabel, menambah kolom, memigrasi data dari format kolom lama ke kolom baru kemudian menjatuhkan kolom, memasukkan baris data "master" seperti jenis pengguna, dll. Pada dasarnya, ini dapat melakukan apa saja, dan dengan data yang tepat skrip migrasi Anda tidak akan pernah kehilangan data.

Skrip pembaruan berfungsi seperti ini:

  • Hubungkan ke database.
  • Buat cadangan dari database saat ini (karena barang akan salah) [mysqldump].
  • Buat tabel pembukuan (disebut _meta) jika tidak ada.
  • Baca VERSION saat ini dari tabel _meta. Asumsikan 0 jika tidak ditemukan.
  • Untuk semua file .sql bernomor lebih tinggi dari VERSION, jalankan secara berurutan
  • Jika salah satu file menghasilkan kesalahan: putar kembali ke cadangan
  • Jika tidak, perbarui versi dalam tabel pembukuan ke file .sql tertinggi yang dijalankan.

Semuanya masuk ke kontrol sumber, dan setiap instalasi memiliki skrip untuk memperbarui ke versi terbaru dengan satu eksekusi skrip (memanggil update.php dengan kata sandi database yang tepat, dll.). Kami SVN memperbarui lingkungan pementasan dan produksi melalui skrip yang secara otomatis memanggil skrip pembaruan basis data, sehingga pembaruan kode dilengkapi dengan pembaruan basis data yang diperlukan.

Kita juga dapat menggunakan skrip yang sama untuk membuat ulang seluruh database dari awal; kami hanya melepas dan membuat ulang database, lalu menjalankan skrip yang akan mengisi kembali database sepenuhnya. Kami juga dapat menggunakan skrip untuk mengisi database kosong untuk pengujian otomatis.


Hanya perlu beberapa jam untuk menyiapkan sistem ini, secara konseptual sederhana dan semua orang mendapatkan skema penomoran versi, dan sangat berharga dalam memiliki kemampuan untuk bergerak maju dan mengembangkan desain database, tanpa harus berkomunikasi atau menjalankan modifikasi secara manual. di semua database.

Berhati-hatilah saat menempelkan kueri dari phpMyAdmin! Kueri yang dihasilkan tersebut biasanya menyertakan nama database, yang pasti tidak Anda inginkan karena akan merusak skrip Anda! Sesuatu seperti CREATE TABLE mydb. newtable(...) akan gagal jika database pada sistem tidak disebut mydb. Kami membuat hook SVN pra-komentar yang akan melarang file .sql yang berisi mydbstring, yang merupakan tanda pasti bahwa seseorang menyalin / menempel dari phpMyAdmin tanpa pemeriksaan yang benar.

rix0rrr
sumber
Bagaimana Anda menangani tabrakan? Beberapa pengembang mengubah elemen yang sama di DB, misalnya prosedur tersimpan? Hal ini dapat terjadi jika Anda bekerja di cabang yang sama, atau Anda memiliki dua jalur pengembangan yang berjalan (dua cabang)
Asaf Mesika
Tabrakan sangat jarang terjadi; satu-satunya hal yang benar-benar terjadi adalah dua orang akan mencoba membuat file N.sql yang sama. Tentu saja, yang pertama menang dan yang kedua dipaksa untuk mengganti nama ke angka tertinggi berikutnya dan coba lagi. Kami tidak memiliki versi database di cabang.
rix0rrr
12

Tim saya membuat skrip semua perubahan database, dan melakukan skrip tersebut ke SVN, bersama dengan setiap rilis aplikasi. Hal ini memungkinkan adanya perubahan bertahap dari database, tanpa kehilangan data apa pun.

Untuk beralih dari satu rilis ke rilis berikutnya, Anda hanya perlu menjalankan sekumpulan skrip perubahan, dan database Anda mutakhir, dan Anda masih memiliki semua data Anda. Ini mungkin bukan metode termudah, tetapi pasti efektif.

Brandon Wood
sumber
1
bagaimana Anda membuat skrip semua perubahan?
Smith
10

Masalah di sini benar-benar memudahkan pengembang untuk membuat skrip perubahan lokal mereka sendiri ke dalam kontrol sumber untuk dibagikan dengan tim. Saya telah menghadapi masalah ini selama bertahun-tahun, dan terinspirasi oleh fungsionalitas Visual Studio untuk profesional Database. Jika Anda menginginkan alat sumber terbuka dengan fitur yang sama, coba ini: http://dbsourcetools.codeplex.com/ Selamat bersenang-senang, - Nathan.


sumber
10

Jika Anda masih mencari solusi: kami mengusulkan alat yang disebut desainer neXtep. Ini adalah lingkungan pengembangan basis data yang dengannya Anda dapat menempatkan seluruh basis data di bawah kendali versi. Anda bekerja pada repositori terkontrol versi di mana setiap perubahan dapat dilacak.

Saat Anda perlu merilis pembaruan, Anda dapat memasukkan komponen Anda dan produk akan secara otomatis menghasilkan skrip peningkatan SQL dari versi sebelumnya. Tentu saja, Anda dapat membuat SQL ini dari 2 versi apa pun.

Kemudian Anda memiliki banyak opsi: Anda dapat mengambil skrip tersebut dan meletakkannya di SVN dengan kode aplikasi Anda sehingga akan diterapkan oleh mekanisme yang ada. Opsi lainnya adalah menggunakan mekanisme pengiriman neXtep: skrip diekspor dalam sesuatu yang disebut "paket pengiriman" (skrip SQL + deskriptor XML), dan penginstal dapat memahami paket ini dan menerapkannya ke server target sambil memastikan konsistensi struktural, ketergantungan periksa, daftarkan versi yang diinstal, dll.

Produknya adalah GPL dan didasarkan pada Eclipse sehingga dapat dijalankan di Linux, Mac dan windows. Ini juga mendukung Oracle, Mysql dan Postgresql saat ini (dukungan DB2 sedang dalam perjalanan). Kunjungi wiki di mana Anda akan menemukan informasi lebih rinci: http://www.nextep-softwares.com/wiki

Christophe Fondacci
sumber
Terlihat menarik. Apakah itu memiliki antarmuka baris perintah juga, atau ada yang direncanakan?
Piskvor meninggalkan gedung
8

Scott Ambler menghasilkan serangkaian artikel hebat (dan ikut menulis buku ) tentang pemfaktoran ulang database, dengan gagasan bahwa Anda pada dasarnya harus menerapkan prinsip dan praktik TDD untuk mempertahankan skema Anda. Anda menyiapkan serangkaian pengujian unit data struktur dan benih untuk database. Kemudian, sebelum Anda mengubah apa pun, Anda memodifikasi / menulis tes untuk mencerminkan perubahan itu.

Kami telah melakukan ini untuk sementara waktu sekarang dan tampaknya berhasil. Kami menulis kode untuk menghasilkan nama kolom dasar dan pemeriksaan tipe data dalam rangkaian pengujian unit. Kami dapat menjalankan kembali pengujian tersebut kapan saja untuk memverifikasi bahwa database di checkout SVN cocok dengan live db yang sebenarnya dijalankan aplikasi.

Ternyata, pengembang terkadang juga mengubah basis data kotak pasir mereka dan lalai memperbarui file skema di SVN. Kode kemudian bergantung pada perubahan db yang belum diperiksa. Bug semacam itu bisa sangat sulit untuk dijabarkan, tetapi rangkaian pengujian akan segera mengambilnya. Ini sangat bagus jika Anda telah membuatnya menjadi rencana Integrasi Berkelanjutan yang lebih besar.

Sam McAfee
sumber
7

Buang skema Anda ke dalam file dan tambahkan ke kontrol sumber. Kemudian perbedaan sederhana akan menunjukkan kepada Anda apa yang berubah.

programer mati
sumber
1
Dump harus dalam SQL, seperti mysqldump, dump Oracle adalah biner.
Osama Al-Maadeed
7
Ada juga masalah yang lebih mendasar dengan schema diffing. Bagaimana Anda membedakan kolom drop + add dari kolom rename. Jawabannya sederhana: Anda tidak bisa. Inilah alasan mengapa Anda perlu merekam operasi perubahan skema yang sebenarnya.
psp
Perbedaan akan menunjukkan bahwa satu kolom hilang, sementara yang lain muncul (kecuali mereka memiliki nama yang sama), dan seringkali itu cukup. Membuat skrip setiap perubahan skema adalah cara yang baik, tentu saja: di Drupal ini ditangani oleh hook khusus, misalnya.
deadprogrammer
5

Ini agak berteknologi rendah, dan mungkin ada solusi yang lebih baik di luar sana, tetapi Anda bisa menyimpan skema Anda dalam skrip SQL yang dapat dijalankan untuk membuat database. Saya pikir Anda dapat menjalankan perintah untuk menghasilkan skrip ini, tetapi sayangnya saya tidak tahu perintahnya.

Kemudian, komit skrip ke kontrol sumber bersama dengan kode yang bekerja padanya. Saat Anda perlu mengubah skema bersama dengan kodenya, skrip dapat diperiksa bersama dengan kode yang memerlukan skema yang diubah. Kemudian, perbedaan pada skrip akan menunjukkan perbedaan pada perubahan skema.

Dengan skrip ini, Anda dapat mengintegrasikannya dengan DBUnit atau semacam skrip build, sehingga sepertinya skrip ini cocok dengan proses otomatis Anda.

Mike Stone
sumber
Ya, itu cukup banyak yang kita miliki sekarang. Sayangnya itu tidak memberi kita cara mudah untuk memodifikasi database yang ada - skrip SQL yang dihasilkan oleh mysqldump mengasumsikan Anda membuat tabel dari awal (atau menimpa tabel jika ada). Kita membutuhkan sesuatu yang lebih berteknologi tinggi karena ia perlu menerapkan urutan pernyataan ALTER TABLE ke database, dan untuk melakukannya dengan benar, ia perlu mengetahui status database saat ini.
pix0r
5

Jika Anda menggunakan C #, lihat Subsonik, alat ORM yang sangat berguna, tetapi juga menghasilkan skrip sql untuk membuat ulang skema dan \ atau data Anda. Skrip ini kemudian dapat dimasukkan ke dalam kontrol sumber.

http://subsonicproject.com/

Dan
sumber
Tampaknya URL mati untuk saat ini.
Mark Schultheiss
5

Saya telah menggunakan struktur proyek database berikut di Visual Studio untuk beberapa proyek dan itu bekerja dengan cukup baik:

Database

Ubah Skrip

0.PreDeploy.sql

1.SchemaChanges.sql

2. DataChanges.sql

3.Permissions.sql

Buat Skrip

Sprocs

Fungsi

Tampilan

Sistem build kami kemudian mengupdate database dari satu versi ke versi berikutnya dengan menjalankan skrip dalam urutan berikut:

1.PreDeploy.sql

2.SchemaChanges.sql

Isi folder Create Scripts

2. DataChanges.sql

3.Permissions.sql

Setiap pengembang memeriksa perubahan mereka untuk bug / fitur tertentu dengan menambahkan kode mereka ke akhir setiap file. Setelah versi utama selesai dan bercabang di kontrol sumber, konten file .sql di folder Ubah Skrip dihapus.

tbreffni.dll
sumber
5

Kami menggunakan solusi yang sangat sederhana namun efektif.

Untuk penginstalan baru, kami memiliki file metadata.sql di repositori yang menampung semua skema DB, lalu dalam proses build kami menggunakan file ini untuk menghasilkan database.

Untuk pembaruan, kami menambahkan pembaruan dalam perangkat lunak yang di-hardcode. Kami menyimpannya dengan hardcode karena kami tidak suka menyelesaikan masalah sebelum itu benar-benar IS masalah, dan hal semacam ini tidak terbukti menjadi masalah sejauh ini.

Jadi dalam perangkat lunak kami, kami memiliki sesuatu seperti ini:

RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

Kode ini akan memeriksa apakah database dalam versi 1 (yang disimpan dalam tabel yang dibuat secara otomatis), jika sudah usang, maka perintah dijalankan.

Untuk memperbarui metadata.sql di repositori, kami menjalankan pemutakhiran ini secara lokal dan kemudian mengekstrak metadata database lengkap.

Satu-satunya hal yang sering terjadi, adalah lupa mengkomit metadata.sql, tetapi ini bukan masalah besar karena mudah untuk menguji proses build dan juga satu-satunya hal yang dapat terjadi adalah membuat instalasi baru dengan database yang kedaluwarsa dan memutakhirkannya pada penggunaan pertama.

Kami juga tidak mendukung penurunan, tetapi sesuai desain, jika ada yang rusak pada pembaruan, kami memulihkan versi sebelumnya dan memperbaiki pembaruan sebelum mencoba lagi.

Fabio Gomes
sumber
4

Saya membuat folder dengan nama versi build dan meletakkan skrip upgrade dan downgrade di sana. Misalnya, Anda dapat memiliki folder berikut: 1.0.0, 1.0.1 dan 1.0.2. Masing-masing berisi skrip yang memungkinkan Anda memutakhirkan atau menurunkan versi database antar versi.

Jika klien atau pelanggan menghubungi Anda dengan masalah dengan versi 1.0.1 dan Anda menggunakan 1.0.2, mengembalikan database ke versinya tidak akan menjadi masalah.

Di database Anda, buat tabel yang disebut "skema" tempat Anda memasukkan versi database saat ini. Maka menulis program yang dapat mengupgrade atau downgrade database Anda dengan mudah.

Seperti yang Joey katakan, jika Anda berada di dunia Rails, gunakan Migrasi. :)

Louis Salin
sumber
3

Untuk proyek PHP saya saat ini, kami menggunakan ide migrasi rel dan kami memiliki direktori migrasi tempat kami menyimpan judul file "migrasi_XX.sql" di mana XX adalah nomor migrasi. Saat ini file-file ini dibuat dengan tangan saat pembaruan dibuat, tetapi pembuatannya dapat dengan mudah dimodifikasi.

Kemudian kami memiliki skrip yang disebut "Migration_watcher" yang, karena kami berada di pra-alfa, saat ini berjalan di setiap pemuatan halaman dan memeriksa apakah ada file migrasi_XX.sql baru di mana XX lebih besar dari versi migrasi saat ini. Jika demikian, ia menjalankan semua file migrasi_XX.sql hingga jumlah terbesar terhadap database dan voila! perubahan skema otomatis.

Jika Anda memerlukan kemampuan untuk mengembalikan sistem akan membutuhkan banyak penyesuaian, tetapi ini sederhana dan telah bekerja dengan sangat baik untuk tim kami yang cukup kecil sejauh ini.

Eric Scrivner
sumber
3

Saya akan merekomendasikan menggunakan Ant (cross platform) untuk sisi "scripting" (karena secara praktis dapat berbicara dengan db manapun di luar sana melalui jdbc) dan Subversion untuk repositori sumber. Ant akan memungkinkan Anda untuk "mencadangkan" db Anda ke file lokal, sebelum membuat perubahan. 1. backup skema db yang ada ke file melalui Ant 2. kontrol versi ke repositori Subversion melalui Ant 3. kirim pernyataan sql baru ke db melalui Ant

Cruz
sumber
3

Toad untuk MySQL memiliki fungsi yang disebut perbandingan skema yang memungkinkan Anda untuk menyinkronkan 2 database. Ini adalah alat terbaik yang pernah saya gunakan sejauh ini.

Petah
sumber
3

Saya suka cara Yii menangani migrasi database. Migrasi pada dasarnya adalah implementasi skrip PHP CDbMigration. CDbMigrationmendefinisikan upmetode yang berisi logika migrasi. Dimungkinkan juga untuk mengimplementasikan downmetode untuk mendukung pembalikan migrasi. Atau, safeUpatausafeDown dapat digunakan untuk memastikan bahwa migrasi dilakukan dalam konteks transaksi.

Alat baris perintah Yii yiicberisi dukungan untuk membuat dan menjalankan migrasi. Migrasi dapat diterapkan atau dibalik, baik satu per satu atau dalam kelompok. Membuat hasil migrasi dalam kode untuk implementasi kelas PHPCDbMigration , diberi nama unik berdasarkan stempel waktu dan nama migrasi yang ditentukan oleh pengguna. Semua migrasi yang sebelumnya telah diterapkan ke database disimpan dalam tabel migrasi.

Untuk informasi selengkapnya, lihat artikel Migrasi Database dari manual.

Ton van den Heuvel
sumber
2

Migrasi IMHO memang memiliki masalah besar:

Memutakhirkan dari satu versi ke versi lain berfungsi dengan baik, tetapi melakukan penginstalan baru dari versi tertentu mungkin membutuhkan waktu lama jika Anda memiliki ratusan tabel dan riwayat perubahan yang panjang (seperti yang kami lakukan).

Menjalankan seluruh histori delta sejak baseline hingga versi saat ini (untuk ratusan database pelanggan) mungkin membutuhkan waktu yang sangat lama.

Edson Medina
sumber
0

Ada alat baris perintah mysql-diff yang membandingkan skema database, di mana skema dapat berupa database langsung atau skrip SQL pada disk. Ini bagus untuk sebagian besar tugas migrasi skema.

stepancheg.dll
sumber