Memodifikasi kolom tabel mysql yang sangat besar dengan sedikit atau tanpa downtime

18

Saya secara berkala perlu membuat perubahan pada tabel di mysql 5.1, kebanyakan menambahkan kolom. Sangat sederhana dengan perintah alter table. Tapi meja saya memiliki hingga 40 juta baris sekarang dan mereka tumbuh cepat ... Jadi perintah-perintah perubahan tabel itu memakan waktu beberapa jam. Dalam beberapa bulan mereka akan membutuhkan berhari-hari.

Karena saya menggunakan amazon RDS, saya tidak bisa memiliki server pendukung untuk bermain dan kemudian mempromosikannya menjadi master. Jadi pertanyaan saya adalah apakah ada cara untuk melakukan ini dengan downtime minimal? Saya tidak keberatan operasi memakan waktu berjam-jam atau bahkan berhari-hari jika pengguna masih dapat menggunakan db tentu saja ... Bisakah mereka setidaknya membaca ketika kolom sedang ditambahkan? Apa yang terjadi jika aplikasi saya mencoba menulis? Sisipkan atau perbarui? Jika gagal segera itu sebenarnya tidak terlalu buruk, jika hanya hang dan menyebabkan masalah untuk server db itu masalah besar ..

Ini harus menjadi masalah penskalaan yang cukup umum, semua orang perlu menambahkan kolom .. Apa yang biasanya dilakukan pada db produksi? Budak -> migrasi master?

Perbarui - Saya lupa menyebutkan saya menggunakan mesin penyimpanan innodb

apptree
sumber
1
Dalam kasus seseorang masih mencari jawaban .. blog.staginginstance.com/ ... ^^
Coder anonim

Jawaban:

10

Saya secara berkala perlu membuat perubahan pada tabel di mysql 5.1, kebanyakan menambahkan kolom.

Jangan. Tidak benar-benar. Hanya saja, jangan. Ini harus menjadi kesempatan yang sangat langka ketika ini pernah diperlukan.

Dengan asumsi data Anda benar-benar dinormalisasi untuk memulai, cara yang tepat untuk menyelesaikan masalah adalah dengan menambahkan tabel baru dengan hubungan 1: 1 ke tabel dasar (tidak wajib pada tabel baru).

Harus menambahkan kolom secara teratur biasanya merupakan indikator dari database yang tidak dinormalisasi - jika skema Anda tidak dinormalisasi maka itu masalah yang perlu Anda perbaiki.

Akhirnya, jika skema Anda benar-benar dinormalisasi dan Anda benar-benar harus terus menambahkan kolom, maka:

  1. Pastikan Anda memiliki kolom stempel waktu di database atau yang menghasilkan log replikasi
  2. Buat salinan (B) dari tabel (A)
  3. tambahkan kolom baru ke B (ini masih akan diblokir dengan myisam)
  4. nonaktifkan transaksi
  5. ganti nama tabel asli (A) sebagai sesuatu yang lain (cadangan)
  6. ganti nama tabel baru (B) dengan nama tabel asli (A)
  7. memutar ulang transaksi dari awal operasi dari log replikasi atau dari tabel cadangan
  8. aktifkan transaksi.
symcbean
sumber
2
Terima kasih atas pendekatan langkah demi langkah Anda. Apakah benar-benar jarang memodifikasi tabel? Saya mengerti bahwa saya bisa menambahkan tabel lain dengan kolom baru (jika perlu menambahkan kolom) dan minta referensi tabel besar asli dalam hubungan 1: 1. Tetapi tampaknya tidak benar untuk memiliki 15 tabel 1: 1 yang sangat besar ketika mereka semua harus berada dalam 1 tabel ... Kinerja kueri tentu saja kemudian menderita juga, belum lagi masalah pengindeksan. Saya bukan ahli, tetapi database saya dinormalisasi dengan cukup baik dan tampaknya wajar bahwa saya perlu memodifikasi secara berkala ..
apptree
2
"Apakah benar-benar tidak biasa untuk memodifikasi tabel?" - Iya.
symcbean
1
Tidak, tetapi orang dapat berargumen bahwa jika itu terjadi secara TERATUR - bukan sebagai bagian dari peningkatan perangkat lunak utama - maka seseorang perlu dipecat karena tidak menyadari bahwa semua tabel harus ada di tempat pertama. Masalah / trik di sini adalah "teratur", bukan "Sekali setiap beberapa bulan".
TomTom
22
Sebagai seorang pengembang, terutama yang bekerja di perusahaan baru dan muda, saya sangat setuju dengan symcbean dan @TomTom. Berbagai hal berubah, produk berubah, perubahan tujuan bisnis, dan struktur basis data perlu diubah dengannya. Memberikan layanan DBA yang baik berarti mengatakan "ya" untuk perubahan itu, lalu mencari tahu bagaimana menerapkannya secara efisien. Basis data yang sangat dinormalisasi adalah konsep yang telah lama mati. Mereka menghasilkan kinerja yang buruk dan siklus dev lambat.
pents90
4
Jarang mengubah tabel ??? Mungkin di perusahaan besar, tetapi dalam tim tangkas yang cukup sering terjadi, persyaratan berubah ...
tibo
12

Saya hanya harus melakukan ini baru-baru ini. Apa yang direkomendasikan Amazon adalah menggunakan Perangkat Percona. Saya mengunduhnya dan dapat menjalankan sesuatu seperti:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType"

dan itu bekerja dengan baik. Ini memberi tahu Anda berapa banyak waktu yang tersisa dalam proses.

Ini benar-benar membuat tabel baru dengan kolom baru dan kemudian menyalin data yang sudah ada. Lebih lanjut, ini menciptakan pemicu sehingga data baru juga didorong ke tabel baru. Itu kemudian mengubah nama tabel secara otomatis, menjatuhkan tabel lama dan Anda bangun dan berjalan dengan kolom baru dan tidak ada downtime saat Anda menunggu pembaruan.

efreedom
sumber
Tim Percona memiliki tulisan singkat tentang cara mengaktifkan fitur log_bin_trust_function_creators, melalui grup parameter RDS (karena SET GLOBAL log_bin_trust_function_creators = 1 tidak bekerja pada RDS), diperlukan oleh alat perubahan skema pt-online. Lebih detail: percona.com/blog/2016/07/01/pt-online-schema-change-amazon-rds
user1652110
ini berhasil untuk saya
Adiii
4

symcbean memberikan beberapa rekomendasi yang solid .

Untuk menjawab pertanyaan Anda, cara termudah dan terbaik untuk mengurangi dampak adalah dengan memiliki beberapa basis data yang direplikasi. Master ganda dengan prosedur failover yang tepat menghentikan replikasi pada aktif, yang memungkinkan perubahan pada tidak aktif tanpa berdampak aktif.

Anda dapat berpotensi melakukan ini pada database langsung tunggal dan meminimalkan dampak dengan menggunakan prosedur yang mirip dengan yang saya jelaskan dalam jawaban ini . Diakui, ini mirip dengan apa yang dijelaskan symcbean tetapi mencakup rincian teknis. Anda bisa menggunakan bidang auto_increment juga dan bukan hanya cap waktu.

Pada akhirnya, jika kumpulan data Anda tumbuh sangat besar, Anda juga harus mempertimbangkan pengarsipan antara database OLTP dan OLAP . Kumpulan data transaksi Anda tidak perlu terlalu besar, jika Anda mendesain dengan tepat.

Warner
sumber
2

Dari manual: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html

Dalam kebanyakan kasus, ALTER TABLE membuat salinan sementara dari tabel asli. MySQL memasukkan perubahan ke dalam salinan, kemudian menghapus tabel asli dan mengganti nama yang baru. Saat ALTER TABLE dijalankan, tabel aslinya dapat dibaca oleh sesi lain. Pembaruan dan penulisan ke tabel terhenti hingga tabel baru siap, dan kemudian secara otomatis diarahkan ke meja baru tanpa pembaruan yang gagal.

Jadi, membaca akan bekerja dengan baik. Menulis akan terhenti, tetapi dieksekusi setelah itu. Jika Anda ingin mencegah ini, Anda harus memodifikasi perangkat lunak Anda.


sumber
Jadi saya telah melakukan ini dan menonaktifkan bagian-bagian situs saya yang menulis ke tabel yang saya modifikasi sekarang. Sejauh ini saya telah menerima beberapa pengecualian "Kunci waktu tunggu tunggu terlampaui; coba mulai ulang transaksi", itu tidak terlalu buruk. Namun, mereka berada di operasi baca PURELY ...
apptree
0

Saya dalam situasi yang sama di mana saya harus mengubah 1 dari tabel transaksi saya yang hampir 65GB. Saya mendengar 2 solusi

  1. Gunakan ALTER lurus ke depan dan biarkan Jalankan (X jumlah jam atau hari)
  2. Pastikan Anda memiliki kolom stempel waktu di database atau yang menghasilkan log replikasi
    • Buat salinan (B) dari tabel (A)
    • tambahkan kolom baru ke B (ini masih akan diblokir dengan myisam)
    • nonaktifkan transaksi
    • ganti nama tabel asli (A) sebagai sesuatu yang lain (cadangan)
    • ganti nama tabel baru (B) dengan nama tabel asli (A)
pengguna144107
sumber