Saat melakukan pernyataan ALTER TABLE di MySQL, seluruh tabel dikunci-baca (memungkinkan pembacaan bersamaan, tetapi melarang penulisan serentak) selama pernyataan. Jika tabelnya besar, pernyataan INSERT atau UPDATE dapat diblokir untuk waktu yang sangat lama. Apakah ada cara untuk melakukan "perubahan panas", seperti menambahkan kolom sedemikian rupa sehingga tabel masih dapat diperbarui selama proses berlangsung?
Sebagian besar saya tertarik dengan solusi untuk MySQL tetapi saya akan tertarik dengan RDBMS lain jika MySQL tidak dapat melakukannya.
Untuk memperjelas, tujuan saya hanyalah untuk menghindari waktu henti ketika fitur baru yang membutuhkan kolom tabel tambahan didorong ke produksi. Skema database apa pun akan berubah seiring waktu, itu hanya fakta kehidupan. Saya tidak mengerti mengapa kita harus menerima bahwa perubahan ini pasti mengakibatkan downtime; itu lemah.
sumber
Jawaban:
Satu-satunya pilihan lain adalah melakukan secara manual apa yang dilakukan oleh banyak sistem RDBMS ...
- Membuat tabel baru
Anda kemudian dapat menyalin konten tabel lama ke bagian satu per satu. Sementara selalu berhati-hati terhadap INSERT / UPDATE / DELETE pada tabel sumber. (Bisa dikelola oleh pemicu. Meskipun ini akan menyebabkan perlambatan, ini bukan kunci ...)
Setelah selesai, ubah nama tabel sumber, kemudian ganti nama tabel baru. Lebih disukai dalam bertransaksi.
Setelah selesai, kompilasi ulang semua prosedur yang tersimpan, dll. Yang menggunakan tabel itu. Rencana eksekusi kemungkinan besar tidak akan berlaku lagi.
EDIT:
Beberapa komentar telah dibuat tentang batasan ini karena sedikit buruk. Jadi saya pikir saya akan meletakkan perspektif baru untuk menunjukkan mengapa seperti itu ...
sumber
Percona membuat alat bernama pt-online-schema-change yang memungkinkan hal ini dilakukan.
Ini pada dasarnya membuat salinan tabel dan memodifikasi tabel baru. Untuk menjaga agar tabel baru tetap sinkron dengan aslinya, ia menggunakan pemicu untuk memperbarui. Ini memungkinkan tabel asli untuk diakses sementara tabel baru disiapkan di latar belakang.
Ini serupa dengan metode yang disarankan Dems di atas, tetapi melakukannya secara otomatis.
Beberapa alat mereka memiliki kurva belajar, yaitu menghubungkan ke database, tetapi setelah Anda menguasainya, mereka adalah alat yang hebat untuk dimiliki.
Ex:
sumber
Pertanyaan ini dari tahun 2009. Sekarang MySQL menawarkan solusi:
DDL Online (Bahasa Definisi Data)
Ini memungkinkan Anda menyesuaikan keseimbangan antara kinerja dan konkurensi selama operasi DDL, dengan memilih apakah akan memblokir akses ke tabel seluruhnya (klausa LOCK = EXCLUSIVE), mengizinkan kueri tetapi tidak DML (klausa LOCK = SHARED), atau mengizinkan kueri penuh dan DML akses ke tabel (klausa LOCK = NONE). Ketika Anda menghilangkan klausa LOCK atau menentukan LOCK = DEFAULT, MySQL mengizinkan konkurensi sebanyak mungkin tergantung pada jenis operasinya.
Melakukan perubahan di tempat jika memungkinkan, daripada membuat salinan baru tabel, menghindari peningkatan sementara dalam penggunaan ruang disk dan overhead I / O yang terkait dengan menyalin tabel dan merekonstruksi indeks sekunder.
lihat Manual Referensi MySQL 5.6 -> InnoDB dan DDL Online untuk info lebih lanjut.
Tampaknya DDL online juga tersedia di MariaDB
MariaDB KB tentang ALTER TABLE
sumber
Lihat alat pengubah skema online Facebook.
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932
Bukan untuk orang yang lemah hati; tapi itu akan berhasil.
sumber
Saya merekomendasikan Postgres jika itu adalah opsi. Dengan postgres pada dasarnya tidak ada waktu henti dengan prosedur berikut:
Fitur hebat lainnya adalah sebagian besar pernyataan DDL bersifat transaksional, sehingga Anda dapat melakukan seluruh migrasi dalam transaksi SQL, dan jika terjadi kesalahan, semuanya akan dibatalkan.
Saya menulis ini beberapa waktu yang lalu, mungkin ini dapat memberikan lebih banyak wawasan tentang manfaat lainnya.
sumber
Karena Anda bertanya tentang database lain, berikut beberapa informasi tentang Oracle.
Menambahkan kolom NULL ke tabel Oracle adalah operasi yang sangat cepat karena hanya memperbarui kamus data. Ini memegang kunci eksklusif di atas meja untuk waktu yang sangat singkat. Namun, ini akan membatalkan semua prosedur yang disimpan depedan, tampilan, pemicu, dll. Ini akan dikompilasi ulang secara otomatis.
Dari sana jika perlu Anda dapat membuat indeks menggunakan klausa ONLINE. Sekali lagi, hanya kunci kamus data yang sangat pendek. Ini akan membaca seluruh tabel mencari hal-hal untuk diindeks, tetapi tidak memblokir siapa pun saat melakukan ini.
Jika Anda perlu menambahkan kunci asing, Anda dapat melakukannya dan membuat Oracle memercayai Anda bahwa datanya benar. Jika tidak, perlu membaca seluruh tabel dan memvalidasi semua nilai yang bisa lambat (buat indeks Anda terlebih dahulu).
Jika Anda perlu meletakkan nilai default atau yang dihitung ke dalam setiap baris kolom baru, Anda harus menjalankan pembaruan besar-besaran atau mungkin program utilitas kecil yang mengisi data baru. Ini bisa lambat, terutama jika baris menjadi jauh lebih besar dan tidak lagi muat di bloknya. Penguncian dapat dikelola selama proses ini. Karena versi lama aplikasi Anda, yang masih berjalan, tidak mengetahui tentang kolom ini, Anda mungkin memerlukan pemicu licik atau untuk menentukan default.
Dari sana, Anda dapat melakukan peralihan pada server aplikasi Anda ke versi kode yang baru dan itu akan terus berjalan. Jatuhkan pemicu licik Anda.
Alternatifnya, Anda dapat menggunakan DBMS_REDEFINITION yang merupakan kotak hitam yang dirancang untuk melakukan hal semacam ini.
Semua ini sangat merepotkan untuk diuji, dll sehingga kami hanya mengalami gangguan Minggu pagi setiap kali kami merilis versi mayor.
sumber
Jika Anda tidak mampu menyediakan waktu henti untuk database Anda saat melakukan pembaruan aplikasi, Anda harus mempertimbangkan untuk mempertahankan cluster dua node untuk ketersediaan tinggi. Dengan pengaturan replikasi sederhana, Anda dapat melakukan hampir sepenuhnya perubahan struktural online seperti yang Anda sarankan:
Ini tidak selalu mudah tetapi berhasil, biasanya dengan 0 waktu henti! Node kedua tidak harus hanya yang pasif, ia dapat digunakan untuk pengujian, melakukan statistik atau sebagai node fallback. Jika Anda tidak memiliki replikasi infrastruktur dapat diatur dalam satu mesin (dengan dua contoh MySQL).
sumber
Nggak. Jika Anda menggunakan tabel MyISAM, menurut pemahaman saya yang terbaik mereka hanya melakukan kunci tabel - tidak ada kunci catatan, mereka hanya mencoba untuk menjaga semuanya tetap cepat melalui kesederhanaan. (Tabel MySQL lain beroperasi secara berbeda.) Bagaimanapun, Anda dapat menyalin tabel ke tabel lain, mengubahnya, lalu mengubahnya, memperbarui perbedaan.
Ini adalah perubahan yang sangat besar sehingga saya ragu DBMS akan mendukungnya. Dapat dilakukan dengan data di tabel pada awalnya merupakan suatu keuntungan.
sumber
Solusi sementara...
Solusi lain bisa jadi, tambahkan tabel lain dengan kunci utama dari tabel asli, bersama dengan kolom baru Anda.
Isi kunci utama Anda ke tabel baru dan isi nilai untuk kolom baru di tabel baru Anda, dan ubah kueri Anda untuk bergabung dengan tabel ini untuk operasi pemilihan dan Anda juga perlu menyisipkan, perbarui secara terpisah untuk nilai kolom ini.
Ketika Anda bisa mendapatkan waktu henti, Anda dapat mengubah tabel asli, memodifikasi kueri DML Anda dan menjatuhkan tabel baru Anda yang dibuat sebelumnya
Jika tidak, Anda dapat menggunakan metode clustering, replikasi, alat pt-online-schema dari percona
sumber
Menggunakan plugin Innodb, pernyataan ALTER TABLE yang hanya menambah atau menghapus indeks sekunder dapat dilakukan "dengan cepat", yaitu tanpa membangun kembali tabel.
Namun secara umum, di MySQL, ALTER TABLE apa pun melibatkan pembangunan kembali seluruh tabel yang dapat memakan waktu sangat lama (yaitu jika tabel memiliki sejumlah data yang berguna di dalamnya).
Anda benar-benar perlu mendesain aplikasi Anda sehingga pernyataan ALTER TABLE tidak perlu dilakukan secara teratur; Anda tentu tidak ingin ALTER TABLE dilakukan selama menjalankan aplikasi secara normal kecuali Anda siap menunggu atau Anda sedang mengubah tabel kecil.
sumber
Saya akan merekomendasikan salah satu dari dua pendekatan:
Rancang tabel database Anda dengan mempertimbangkan potensi perubahan. Misalnya, saya bekerja dengan Sistem Manajemen Konten, yang mengubah bidang data di konten secara teratur. Alih-alih membangun struktur basis data fisik agar sesuai dengan persyaratan bidang CMS awal, jauh lebih baik membangun dalam struktur yang fleksibel. Dalam kasus ini, menggunakan kolom teks blob (misalnya varchar (max)) untuk menyimpan data XML yang fleksibel. Ini membuat perubahan struktural menjadi sangat jarang. Perubahan struktural bisa jadi mahal, jadi ada manfaat yang harus dibayar di sini juga.
Memiliki waktu pemeliharaan sistem. Sistem akan offline selama ada perubahan (bulanan, dll), dan perubahan dijadwalkan selama waktu yang paling jarang diperdagangkan pada hari itu (misalnya, 3-5 pagi). Perubahan dilakukan secara bertahap sebelum peluncuran produksi, sehingga Anda akan memiliki perkiraan jendela waktu henti yang tetap.
2a. Memiliki server yang redundan, sehingga ketika sistem mengalami downtime, seluruh situs tidak akan down. Ini akan memungkinkan Anda untuk "meluncurkan" pembaruan Anda secara terhuyung-huyung, tanpa menghapus seluruh situs.
Opsi 2 dan 2a mungkin tidak layak; mereka cenderung hanya untuk situs / operasi yang lebih besar. Namun, itu adalah opsi yang valid, dan saya pribadi telah menggunakan semua opsi yang disajikan di sini.
sumber
Jika ada yang masih membaca ini atau kebetulan datang ke sini, inilah keuntungan besar menggunakan sistem database NoSQL seperti mongodb. Saya memiliki masalah yang sama berurusan dengan mengubah tabel untuk menambahkan kolom untuk fitur tambahan atau indeks pada tabel besar dengan jutaan baris dan tulisan tinggi. Ini akan berakhir dengan penguncian untuk waktu yang sangat lama sehingga melakukan ini di database LIVE akan membuat pengguna kami frustrasi. Di meja kecil Anda bisa lolos begitu saja.
Saya benci kenyataan bahwa kita harus "mendesain tabel kita agar tidak mengubahnya". Saya hanya tidak berpikir itu berfungsi di dunia situs web saat ini. Anda tidak dapat memprediksi bagaimana orang akan menggunakan perangkat lunak Anda, itulah sebabnya Anda mengubah hal-hal dengan cepat berdasarkan umpan balik pengguna. Dengan mongodb, Anda dapat menambahkan "kolom" sesuka hati tanpa downtime. Anda bahkan tidak benar-benar menambahkannya, Anda hanya memasukkan data dengan kolom baru dan melakukannya secara otomatis.
Layak untuk dicoba: www.mongodb.com
sumber
Secara umum, jawabannya adalah "Tidak". Anda mengubah struktur tabel yang berpotensi memerlukan banyak pembaruan "dan saya sangat setuju dengan itu. Jika Anda berharap sering melakukan ini, saya akan menawarkan alternatif untuk kolom" tiruan "- gunakan
VIEW
s sebagai gantinya tabel untukSELECT
memasukkan data. IIRC, mengubah definisi tampilan relatif ringan dan tipuan melalui tampilan dilakukan ketika rencana kueri dikompilasi. Biaya yang harus Anda lakukan adalah menambahkan kolom ke tabel baru dan membuat lihatJOIN
di kolom.Tentu saja ini hanya berfungsi jika Anda dapat menggunakan kunci asing untuk melakukan cascading penghapusan dan yang lainnya. Bonus lainnya adalah Anda dapat membuat tabel baru yang berisi kombinasi data dan mengarahkan pandangan ke sana tanpa mengganggu penggunaan klien.
Hanya pemikiran saja.
sumber
Perbedaan antara Postgres dan MySQL dalam hal ini adalah bahwa di Postgres tidak membuat ulang tabel, tetapi memodifikasi kamus data yang mirip dengan Oracle. Oleh karena itu, operasinya cepat, sementara itu masih perlu mengalokasikan kunci tabel DDL eksklusif untuk waktu yang sangat singkat seperti yang dinyatakan di atas oleh orang lain.
Di MySQL, operasi tersebut akan menyalin data ke tabel baru sambil memblokir transaksi, yang merupakan masalah utama untuk DBA MySQL sebelum v. 5.6.
Kabar baiknya adalah sejak rilis MySQL 5.6, pembatasan sebagian besar telah dicabut dan Anda sekarang dapat menikmati kekuatan sebenarnya dari MYSQL DB.
sumber
Seperti yang telah disebutkan SeanDowney,
pt-online-schema-change
ini adalah salah satu alat terbaik untuk melakukan apa yang telah Anda jelaskan dalam pertanyaan di sini. Saya baru-baru ini melakukan banyak perubahan skema pada DB live dan berjalan cukup baik. Anda dapat membaca lebih lanjut tentang itu di posting blog saya di sini: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .sumber
Anda pasti harus mencobanya
pt-online-schema-change
. Saya telah menggunakan alat ini untuk melakukan migrasi di AWS RDS dengan banyak budak dan alat ini bekerja dengan sangat baik untuk saya. Saya menulis posting blog yang terperinci tentang bagaimana melakukan itu yang mungkin berguna bagi Anda.Blog: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/
sumber
Kolom dummy adalah ide yang bagus jika Anda dapat memprediksi tipenya (dan membuatnya menjadi nullable). Periksa bagaimana mesin penyimpanan Anda menangani null.
MyISAM akan mengunci semuanya jika Anda bahkan menyebutkan nama meja secara sepintas, di telepon, di bandara. Itu hanya melakukan itu ...
Karena itu, kunci bukanlah masalah besar; selama Anda tidak mencoba menambahkan nilai default untuk kolom baru ke setiap baris, tetapi membiarkannya sebagai null, dan mesin penyimpanan Anda cukup pintar untuk tidak menulisnya, Anda akan baik-baik saja dengan kunci yang hanya ditahan cukup lama untuk memperbarui metadata. Jika Anda mencoba untuk menulis nilai baru, ya, Anda bersulang.
sumber
TokuDB dapat menambah / menjatuhkan kolom dan menambahkan indeks "panas", tabel sepenuhnya tersedia selama proses tersebut. Ini tersedia melalui www.tokutek.com
sumber
Tidak juga.
Anda SUDAH mengubah struktur dasar tabel, dan itu adalah sedikit informasi yang cukup penting bagi sistem yang mendasarinya. Anda juga (kemungkinan) memindahkan banyak data di sekitar disk.
Jika Anda berencana sering melakukan ini, lebih baik Anda hanya mengisi tabel dengan kolom "dummy" yang tersedia untuk digunakan di masa mendatang.
sumber