[2017] Pembaruan: MySQL 5.6 memiliki dukungan untuk pembaruan indeks online
https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes
Di MySQL 5.6 dan yang lebih tinggi, tabel tetap tersedia untuk operasi baca dan tulis saat indeks dibuat atau dihapus. Pernyataan CREATE INDEX atau DROP INDEX hanya selesai setelah semua transaksi yang mengakses tabel selesai, sehingga status awal indeks mencerminkan konten terbaru dari tabel. Sebelumnya, mengubah tabel saat indeks dibuat atau dihapus biasanya mengakibatkan kebuntuan yang membatalkan pernyataan INSERT, UPDATE, atau DELETE pada tabel.
[2015] Tabel yang diperbarui menunjukkan blok menulis di MySQL 5.5
Dari jawaban di atas:
"Jika Anda menggunakan indeks versi lebih besar dari 5.1 yang dibuat saat database sedang online. Jadi, jangan khawatir Anda tidak akan mengganggu penggunaan sistem produksi."
Ini adalah **** FALSE **** (setidaknya untuk tabel MyISAM / InnoDB, yang digunakan oleh 99,999% orang di luar sana. Edisi Clustered berbeda.)
Melakukan operasi UPDATE di atas meja akan DIBLOKIR saat indeks sedang dibuat. MySQL benar-benar bodoh tentang ini (dan beberapa hal lainnya).
Skrip Tes:
(
for n in {1..50}; do
#(time mysql -uroot -e 'select * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
(time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'
Server Saya (InnoDB):
Server version: 5.5.25a Source distribution
Output (perhatikan bagaimana operasi ke-6 memblokir ~ 400ms yang diperlukan untuk menyelesaikan pembaruan indeks):
1 real 0m0.009s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.012s
5 real 0m0.009s
Index Update - START
Index Update - FINISH
6 real 0m0.388s
7 real 0m0.009s
8 real 0m0.009s
9 real 0m0.009s
10 real 0m0.009s
11 real 0m0.009s
Operasi baca Vs yang tidak memblokir (menukar komentar baris di skrip):
1 real 0m0.010s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.010s
5 real 0m0.009s
Index Update - START
6 real 0m0.010s
7 real 0m0.010s
8 real 0m0.011s
9 real 0m0.010s
...
41 real 0m0.009s
42 real 0m0.010s
43 real 0m0.009s
Index Update - FINISH
44 real 0m0.012s
45 real 0m0.009s
46 real 0m0.009s
47 real 0m0.010s
48 real 0m0.009s
Memperbarui Skema MySQL tanpa waktu henti
Sejauh ini, hanya ada satu metode yang saya ketahui untuk memperbarui skema MySql dan tidak mengalami gangguan ketersediaan. Master melingkar:
- Master A menjalankan database MySQL Anda
- Bawa Master B ke dalam layanan dan minta itu mereplikasi penulisan dari Master A (B adalah budak A)
- Lakukan pembaruan skema pada Master B. Itu akan tertinggal selama peningkatan
- Biarkan Tuan B menyusul. Invarian: Perubahan skema Anda HARUS dapat memproses perintah yang direplikasi dari skema downversion. Perubahan pengindeksan memenuhi syarat. Penambahan kolom sederhana biasanya memenuhi syarat. Menghapus kolom? mungkin tidak.
- SECARA ATOMIS menukar semua klien dari Master A ke Master B.Jika Anda ingin aman (percayalah, Anda lakukan), Anda harus memastikan bahwa penulisan terakhir ke A direplikasi ke B SEBELUMB mengambil tulisan pertamanya. Jika Anda mengizinkan penulisan secara bersamaan ke 2+ master, ... Anda lebih memahami replikasi MySQL pada level DEEP atau Anda sedang menuju dunia yang penuh kesulitan. Sakit yang luar biasa. Seperti, apakah Anda memiliki kolom AUTOINCREMENT ??? Anda kacau (kecuali jika Anda menggunakan angka genap pada satu master dan odds di sisi lain). JANGAN percaya replikasi MySQL untuk "melakukan hal yang benar". Ini TIDAK pintar dan tidak akan menyelamatkan Anda. Ini hanya sedikit kurang aman daripada menyalin log transaksi biner dari baris perintah dan memutarnya kembali dengan tangan. Namun, memutuskan semua klien dari master lama dan membaliknya ke master baru dapat dilakukan dalam hitungan detik, jauh lebih cepat daripada menunggu upgrade skema multi-jam.
- Sekarang Master B adalah master baru Anda. Anda memiliki skema baru. Hidup itu baik. Minum bir; yang terburuk sudah berakhir.
- Ulangi proses ini dengan Master A, tingkatkan skemanya sehingga dia menjadi master sekunder baru Anda, siap untuk mengambil alih jika master utama Anda (master B sekarang) kehilangan kekuasaan atau mati dan mati pada Anda.
Cara mudah untuk memperbarui skema ini bukan. Bisa diterapkan di lingkungan produksi yang serius; ya itu. Tolong, tolong, tolong, jika ada cara yang lebih mudah untuk menambahkan indeks ke tabel MySQL tanpa memblokir penulisan, beri tahu saya.
Googling membawa saya ke artikel ini yang menjelaskan teknik serupa. Lebih baik lagi, mereka menyarankan minum pada titik yang sama dalam proses (Perhatikan bahwa saya menulis jawaban saya sebelum membaca artikel)!
Pt-online-schema-change Percona
The Artikel saya terkait di atas berbicara tentang alat, pt-secara online-skema-perubahan , yang bekerja sebagai berikut:
- Buat tabel baru dengan struktur yang sama seperti aslinya.
- Perbarui skema di tabel baru.
- Tambahkan pemicu pada tabel asli agar perubahan tetap sinkron dengan salinannya
- Salin baris dalam kelompok dari tabel asli.
- Singkirkan tabel asli dan ganti dengan tabel baru.
- Jatuhkan meja lama.
Saya sendiri belum pernah mencoba alat tersebut. YMMV
RDS
Saya saat ini menggunakan MySQL melalui Amazon's RDS . Ini adalah layanan yang sangat bagus yang membungkus dan mengelola MySQL, memungkinkan Anda menambahkan replika baca baru dengan satu tombol dan secara transparan memutakhirkan basis data di seluruh perangkat keras SKU. Sangat nyaman. Anda tidak mendapatkan akses SUPER ke database, jadi Anda tidak dapat mengacaukan replikasi secara langsung (apakah ini berkah atau kutukan?). Namun, Anda dapat menggunakan Promosi Replika Baca untuk mengubah skema Anda pada budak hanya-baca, lalu promosikan budak tersebut menjadi master baru Anda. Trik yang persis sama seperti yang saya jelaskan di atas, hanya saja jauh lebih mudah untuk dieksekusi. Mereka masih tidak berbuat banyak untuk membantu Anda mengatasi masalah ini. Anda harus mengkonfigurasi ulang dan memulai ulang aplikasi Anda.