Skema database bukanlah sesuatu yang tertulis di atas batu. Ini dirancang untuk aplikasi tertentu, tetapi kemudian persyaratannya mungkin dan biasanya berubah. Modul dan fungsionalitas baru ditambahkan ke aplikasi, lebih banyak data dikumpulkan, kode dan refactoring model data dilakukan. Oleh karena itu kebutuhan untuk memodifikasi skema database untuk beradaptasi dengan perubahan ini; menambahkan atau memodifikasi kolom, membuat tabel baru atau mempartisi tabel yang besar. Kueri juga berubah karena pengembang menambahkan cara baru bagi pengguna untuk berinteraksi dengan data - kueri baru dapat menggunakan indeks baru yang lebih efisien, jadi kami bergegas membuatnya untuk menyediakan aplikasi dengan kinerja database terbaik.
Jadi, bagaimana cara terbaik kita mendekati perubahan skema? Alat apa yang berguna? Bagaimana meminimalkan dampak pada database produksi? Apa masalah paling umum dengan desain skema? Alat apa yang dapat membantu Anda untuk tetap berada di atas skema Anda? Dalam posting blog ini kami akan memberikan gambaran singkat tentang bagaimana melakukan perubahan skema di MySQL dan MariaDB. Harap dicatat bahwa kami tidak akan membahas perubahan skema dalam konteks Galera Cluster. Kami telah membahas Total Order Isolation, Rolling Schema Upgrades dan tips untuk meminimalkan dampak dari RSU di posting blog sebelumnya. Kami juga akan membahas tips dan trik yang terkait dengan desain skema dan bagaimana ClusterControl dapat membantu Anda untuk tetap mengetahui semua perubahan skema.
Jenis Perubahan Skema
Hal pertama yang pertama. Sebelum kita menggali topik, kita harus memahami bagaimana MySQL dan MariaDB melakukan perubahan skema. Anda lihat, satu perubahan skema tidak sama dengan perubahan skema lainnya.
Anda mungkin pernah mendengar tentang perubahan online, perubahan instan, atau perubahan di tempat. Semua ini adalah hasil dari pekerjaan yang sedang berlangsung untuk meminimalkan dampak perubahan skema pada database produksi. Secara historis, hampir semua perubahan skema memblokir. Jika Anda menjalankan perubahan skema, semua kueri akan mulai menumpuk, menunggu ALTER selesai. Jelas, ini menimbulkan masalah serius untuk penyebaran produksi. Tentu, orang-orang segera mulai mencari solusi, dan kami akan membahasnya nanti di blog ini, karena hingga saat ini masih relevan. Tetapi juga, pekerjaan mulai meningkatkan kemampuan MySQL untuk menjalankan DDL (Data Definition Language) tanpa banyak dampak pada kueri lainnya.
Perubahan Instan
Terkadang tidak perlu menyentuh data apa pun di tablespace, karena yang harus diubah hanyalah metadata. Contoh di sini akan menjatuhkan indeks atau mengganti nama kolom. Operasi seperti itu cepat dan efisien. Biasanya, dampaknya terbatas. Ini bukan tanpa dampak, meskipun. Terkadang dibutuhkan beberapa detik untuk melakukan perubahan dalam metadata dan perubahan tersebut memerlukan kunci metadata untuk diperoleh. Kunci ini pada basis per-tabel, dan mungkin memblokir operasi lain yang akan dijalankan pada tabel ini. Anda akan melihat ini sebagai entri “Menunggu kunci metadata tabel” di daftar proses.
Contoh perubahan tersebut mungkin instan ADD COLUMN, diperkenalkan di MariaDB 10.3 dan MySQL 8.0. Ini memberikan kemungkinan untuk mengeksekusi perubahan skema yang cukup populer ini tanpa penundaan. Baik MariaDB dan Oracle memutuskan untuk memasukkan kode dari Tencent Game yang memungkinkan untuk langsung menambahkan kolom baru ke tabel. Ini di bawah beberapa kondisi tertentu; kolom harus ditambahkan sebagai yang terakhir, indeks teks lengkap tidak dapat ada di tabel, format baris tidak dapat dikompresi - Anda dapat menemukan informasi lebih lanjut tentang cara kerja kolom penambahan instan di dokumentasi MariaDB. Untuk MySQL, satu-satunya referensi resmi dapat ditemukan di blog mysqlserverteam.com, meskipun ada bug untuk memperbarui dokumentasi resmi.
Perubahan Di Tempat
Beberapa perubahan memerlukan modifikasi data di tablespace. Modifikasi tersebut dapat dilakukan pada data itu sendiri, dan tidak perlu membuat tabel sementara dengan struktur data baru. Perubahan seperti itu, biasanya (walaupun tidak selalu) memungkinkan kueri lain yang menyentuh tabel untuk dieksekusi saat perubahan skema sedang berjalan. Contoh operasi tersebut adalah menambahkan indeks sekunder baru ke tabel. Operasi ini akan memakan waktu untuk dilakukan tetapi akan memungkinkan DML untuk dieksekusi.
Pembuatan Ulang Tabel
Jika tidak memungkinkan untuk membuat perubahan di tempat, InnoDB akan membuat tabel sementara dengan struktur baru yang diinginkan. Ini kemudian akan menyalin data yang ada ke tabel baru. Operasi ini adalah yang paling mahal dan kemungkinan (walaupun tidak selalu terjadi) untuk mengunci DML. Akibatnya, perubahan skema seperti itu sangat sulit untuk dieksekusi pada tabel besar di server mandiri, tanpa bantuan alat eksternal - biasanya Anda tidak dapat mengunci database selama beberapa menit atau bahkan berjam-jam. Contoh operasi tersebut adalah mengubah tipe data kolom, misalnya dari INT ke VARCHAR.
Perubahan dan Replikasi Skema
Oke, jadi kita tahu bahwa InnoDB mengizinkan perubahan skema online dan jika kita berkonsultasi dengan dokumentasi MySQL, kita akan melihat bahwa sebagian besar perubahan skema (setidaknya di antara yang paling umum) dapat dilakukan secara online. Apa alasan di balik mendedikasikan jam pengembangan untuk membuat alat pengubah skema online seperti gh-ost? Kami dapat menerima bahwa pt-online-schema-change adalah sisa dari masa lalu yang buruk, tetapi gh-ost adalah perangkat lunak baru.
Jawabannya kompleks. Ada dua masalah utama.
Sebagai permulaan, setelah Anda memulai perubahan skema, Anda tidak memiliki kendali atasnya. Anda dapat membatalkannya tetapi Anda tidak dapat menghentikannya. Anda tidak bisa mencekiknya. Seperti yang dapat Anda bayangkan, membangun kembali tabel adalah operasi yang mahal dan bahkan jika InnoDB mengizinkan DML dijalankan, beban kerja I/O tambahan dari DDL memengaruhi semua kueri lainnya dan tidak ada cara untuk membatasi dampak ini ke tingkat yang dapat diterima oleh aplikasi.
Kedua, masalah yang lebih serius lagi, adalah replikasi. Jika Anda menjalankan operasi non-pemblokiran, yang memerlukan pembuatan ulang tabel, itu memang tidak akan mengunci DML tetapi ini hanya berlaku pada master. Mari kita asumsikan DDL seperti itu membutuhkan waktu 30 menit untuk diselesaikan - kecepatan ALTER tergantung pada perangkat keras tetapi cukup umum untuk melihat waktu eksekusi seperti itu pada tabel dengan rentang ukuran 20GB. Kemudian direplikasi ke semua slave dan, sejak DDL dimulai pada slave tersebut, replikasi akan menunggu hingga selesai. Tidak masalah jika Anda menggunakan MySQL atau MariaDB, atau jika Anda memiliki replikasi multi-utas. Budak akan tertinggal - mereka akan menunggu 30 menit untuk menyelesaikan DDL sebelum mulai menerapkan peristiwa binlog yang tersisa. Seperti yang dapat Anda bayangkan, jeda 30 menit (kadang-kadang bahkan 30 detik tidak dapat diterima - semuanya tergantung pada aplikasi) adalah sesuatu yang membuat tidak mungkin menggunakan slave tersebut untuk scale-out. Tentu saja, ada solusi - Anda dapat melakukan perubahan skema dari bawah ke atas rantai replikasi tetapi ini sangat membatasi pilihan Anda. Terutama jika Anda menggunakan replikasi berbasis baris, Anda hanya dapat menjalankan perubahan skema yang kompatibel dengan cara ini. Beberapa contoh keterbatasan replikasi berbasis baris; Anda tidak dapat menjatuhkan kolom apa pun yang bukan yang terakhir, Anda tidak dapat menambahkan kolom ke posisi selain yang terakhir. Anda juga tidak dapat mengubah jenis kolom (misalnya, INT -> VARCHAR).
Seperti yang Anda lihat, replikasi menambah kerumitan bagaimana Anda bisa melakukan perubahan skema. Operasi yang non-blocking pada host standalone menjadi blocking saat dijalankan pada slave. Mari kita lihat beberapa metode yang dapat Anda gunakan untuk meminimalkan dampak perubahan skema.
Alat Pengubah Skema Online
Seperti yang kami sebutkan sebelumnya, ada alat, yang dimaksudkan untuk melakukan perubahan skema. Yang paling populer adalah pt-online-schema-change yang dibuat oleh Percona dan gh-ost, yang dibuat oleh GitHub. Dalam serangkaian posting blog kami membandingkannya dan mendiskusikan bagaimana gh-ost dapat digunakan untuk melakukan perubahan skema dan bagaimana Anda dapat membatasi dan mengonfigurasi ulang migrasi yang sedang berlangsung. Di sini kita tidak akan masuk ke rincian, tapi kami masih ingin menyebutkan beberapa aspek yang paling penting dari penggunaan alat tersebut. Sebagai permulaan, perubahan skema yang dijalankan melalui pt-osc atau gh-ost akan terjadi pada semua node database sekaligus. Tidak ada penundaan apapun dalam hal kapan perubahan akan diterapkan. Hal ini memungkinkan untuk menggunakan alat tersebut bahkan untuk perubahan skema yang tidak kompatibel dengan replikasi berbasis baris. Mekanisme yang tepat tentang bagaimana alat-alat tersebut melacak perubahan pada tabel berbeda (pemicu di pt-osc vs parsing binlog di gh-ost) tetapi ide utamanya sama - tabel baru dibuat dengan skema yang diinginkan dan data yang ada adalah disalin dari tabel lama. Sementara itu, DML dilacak (dengan satu atau lain cara) dan diterapkan ke tabel baru. Setelah semua data dimigrasikan, tabel diganti namanya dan tabel baru menggantikan yang lama. Ini adalah operasi atom sehingga tidak terlihat oleh aplikasi. Kedua alat memiliki opsi untuk membatasi beban dan menghentikan operasi. Gh-ost dapat menghentikan semua aktivitas, pt-osc hanya dapat menghentikan proses penyalinan data antara tabel lama dan baru - pemicu akan tetap aktif dan mereka akan terus menduplikasi data, yang menambahkan beberapa overhead. Karena tabel rename, kedua alat memiliki beberapa keterbatasan terkait kunci asing - tidak didukung oleh gh-ost, sebagian didukung oleh pt-osc baik melalui ALTER biasa, yang dapat menyebabkan jeda replikasi (tidak layak jika tabel anak besar) atau oleh menjatuhkan tabel lama sebelum mengganti nama tabel baru - ini berbahaya karena tidak ada cara untuk mengembalikan jika, karena alasan tertentu, data tidak disalin ke tabel baru dengan benar. Pemicunya juga sulit untuk didukung.
Mereka tidak didukung di gh-ost, pt-osc di MySQL 5.7 dan yang lebih baru memiliki dukungan terbatas untuk tabel dengan pemicu yang ada. Keterbatasan penting lainnya untuk alat perubahan skema online adalah bahwa kunci unik atau kunci utama harus ada di tabel. Ini digunakan untuk mengidentifikasi baris yang akan disalin antara tabel lama dan baru. Alat tersebut juga jauh lebih lambat daripada ALTER langsung - perubahan yang membutuhkan waktu berjam-jam saat menjalankan ALTER mungkin memerlukan waktu berhari-hari jika dilakukan menggunakan pt-osc atau gh-ost.
Di sisi lain, seperti yang kami sebutkan, selama persyaratan terpenuhi dan batasan tidak ikut bermain, Anda dapat menjalankan semua perubahan skema menggunakan salah satu alat. Semua akan terjadi pada waktu yang sama di semua host sehingga Anda tidak perlu khawatir tentang kompatibilitas. Anda juga memiliki beberapa tingkat kontrol atas bagaimana proses dijalankan (lebih sedikit di pt-osc, lebih banyak di gh-ost).
Anda dapat mengurangi dampak perubahan skema, Anda dapat menjedanya dan membiarkannya berjalan hanya di bawah pengawasan, Anda dapat menguji perubahan sebelum benar-benar menjalankannya. Anda dapat meminta mereka melacak jeda dan jeda replikasi jika dampaknya terdeteksi. Ini menjadikan alat tersebut sebagai tambahan yang sangat bagus untuk gudang senjata DBA saat bekerja dengan replikasi MySQL.
Perubahan Skema Bergulir
Biasanya, DBA akan menggunakan salah satu alat perubahan skema online. Tetapi seperti yang telah kita bahas sebelumnya, dalam beberapa keadaan, mereka tidak dapat digunakan dan perubahan langsung adalah satu-satunya pilihan yang layak. Jika kita berbicara tentang MySQL mandiri, Anda tidak punya pilihan - jika perubahannya tidak memblokir, itu bagus. Jika tidak, yah, tidak ada yang bisa Anda lakukan. Tapi kemudian, tidak banyak orang yang menjalankan MySQL sebagai instance tunggal, bukan? Bagaimana dengan replikasi? Seperti yang telah kita bahas sebelumnya, perubahan langsung pada master tidak dapat dilakukan - sebagian besar kasus akan menyebabkan kelambatan pada slave dan ini mungkin tidak dapat diterima. Namun, apa yang bisa dilakukan adalah menjalankan perubahan secara bergulir. Anda dapat mulai dengan budak dan, setelah perubahan diterapkan pada semuanya, promosikan salah satu budak sebagai master baru, turunkan master lama menjadi budak dan jalankan perubahan di atasnya. Tentu, perubahan harus kompatibel tetapi, sejujurnya, kasus paling umum di mana Anda tidak dapat menggunakan perubahan skema online adalah karena kurangnya kunci utama atau unik. Untuk semua kasus lain, ada semacam solusi, terutama di pt-online-schema-change karena gh-ost memiliki batasan yang lebih sulit. Ini adalah solusi yang Anda sebut "begitu begitu" atau "jauh dari ideal", tetapi itu akan berhasil jika Anda tidak memiliki pilihan lain untuk dipilih. Yang juga penting, sebagian besar batasan dapat dihindari jika Anda memantau skema Anda dan menangkap masalah sebelum tabel bertambah. Bahkan jika seseorang membuat tabel tanpa kunci utama, tidak menjadi masalah untuk menjalankan perubahan langsung yang membutuhkan waktu setengah detik atau kurang, karena tabel hampir kosong.
Jika itu akan tumbuh, ini akan menjadi masalah serius tetapi terserah DBA untuk menangkap masalah semacam ini sebelum mereka benar-benar mulai membuat masalah. Kami akan membahas beberapa tip dan trik tentang cara memastikan Anda akan menangkap masalah seperti itu tepat waktu. Kami juga akan membagikan tips umum tentang cara mendesain skema Anda.
Kiat dan Trik
Desain Skema
Seperti yang kami tunjukkan dalam posting ini, alat perubahan skema online cukup penting ketika bekerja dengan pengaturan replikasi oleh karena itu sangat penting untuk memastikan skema Anda dirancang sedemikian rupa sehingga tidak akan membatasi opsi Anda untuk melakukan perubahan skema. Ada tiga aspek penting. Pertama, kunci utama atau unik harus ada - Anda perlu memastikan tidak ada tabel tanpa kunci utama di database Anda. Anda harus memantau ini secara teratur, jika tidak maka dapat menjadi masalah serius di masa depan. Kedua, Anda harus mempertimbangkan dengan serius apakah menggunakan kunci asing adalah ide yang bagus. Tentu, mereka memiliki kegunaannya tetapi mereka juga menambahkan overhead ke database Anda dan mereka dapat membuatnya bermasalah untuk menggunakan alat perubahan skema online. Hubungan dapat ditegakkan oleh aplikasi. Bahkan jika itu berarti lebih banyak pekerjaan, itu masih mungkin ide yang lebih baik daripada mulai menggunakan kunci asing dan sangat terbatas pada jenis perubahan skema yang dapat dilakukan. Ketiga, pemicu. Cerita yang sama seperti dengan kunci asing. Mereka adalah fitur yang bagus untuk dimiliki, tetapi mereka bisa menjadi beban. Anda perlu mempertimbangkan secara serius apakah keuntungan dari menggunakannya melebihi batasan yang mereka timbulkan.
Perubahan Skema Pelacakan
Manajemen perubahan skema bukan hanya tentang menjalankan perubahan skema. Anda juga harus tetap berada di atas struktur skema Anda, terutama jika Anda bukan satu-satunya yang melakukan perubahan.
ClusterControl memberi pengguna alat untuk melacak beberapa masalah desain skema yang paling umum. Ini dapat membantu Anda melacak tabel yang tidak memiliki kunci utama:
Seperti yang telah kita bahas sebelumnya, menangkap tabel seperti itu lebih awal sangat penting karena kunci utama harus ditambahkan menggunakan perubahan langsung.
ClusterControl juga dapat membantu Anda melacak indeks duplikat. Biasanya, Anda tidak ingin memiliki banyak indeks yang berlebihan. Pada contoh di atas, Anda dapat melihat bahwa ada indeks di (k, c) dan ada juga indeks di (k). Setiap kueri yang dapat menggunakan indeks yang dibuat pada kolom 'k' juga dapat menggunakan indeks komposit yang dibuat pada kolom (k, c). Ada kasus-kasus di mana menyimpan indeks yang berlebihan itu bermanfaat tetapi Anda harus mendekatinya berdasarkan kasus per kasus. Mulai dari MySQL 8.0, dimungkinkan untuk menguji dengan cepat apakah suatu indeks benar-benar dibutuhkan atau tidak. Anda dapat membuat indeks redundan 'tidak terlihat' dengan menjalankan:
ALTER TABLE sbtest.sbtest1 ALTER INDEX k_1 INVISIBLE;
Ini akan membuat MySQL mengabaikan indeks itu dan, melalui pemantauan, Anda dapat memeriksa apakah ada dampak negatif pada kinerja database. Jika semuanya berjalan sesuai rencana untuk beberapa waktu (beberapa hari atau bahkan berminggu-minggu), Anda dapat merencanakan untuk menghapus file index. Jika Anda mendeteksi ada yang tidak beres, Anda selalu dapat mengaktifkan kembali indeks ini dengan menjalankan:
ALTER TABLE sbtest.sbtest1 ALTER INDEX k_1 VISIBLE;
Operasi tersebut instan dan indeks ada sepanjang waktu, dan masih dipertahankan - hanya saja itu tidak akan dipertimbangkan oleh pengoptimal. Berkat opsi ini, menghapus indeks di MySQL 8.0 akan menjadi operasi yang jauh lebih aman. Di versi sebelumnya, menambahkan kembali indeks yang salah dihapus bisa memakan waktu berjam-jam jika bukan berhari-hari di tabel besar.
ClusterControl juga dapat memberi tahu Anda tentang tabel MyISAM.
Meskipun MyISAM mungkin masih memiliki kegunaannya, Anda harus ingat bahwa ini bukan mesin penyimpanan transaksional. Dengan demikian, ini dapat dengan mudah memperkenalkan inkonsistensi data antar node dalam pengaturan replikasi.
Fitur lain yang sangat berguna dari ClusterControl adalah salah satu laporan operasional - Laporan Perubahan Skema.
Di dunia yang ideal, DBA meninjau, menyetujui, dan mengimplementasikan semua perubahan skema. Sayangnya, hal ini tidak selalu terjadi. Proses peninjauan seperti itu tidak berjalan dengan baik dengan pengembangan tangkas. Selain itu, rasio Pengembang-ke-DBA biasanya cukup tinggi yang juga dapat menjadi masalah karena DBA akan berjuang untuk tidak menjadi hambatan. Itulah mengapa tidak jarang melihat perubahan skema dilakukan di luar pengetahuan DBA. Namun, DBA biasanya yang bertanggung jawab atas kinerja dan stabilitas database. Berkat Laporan Perubahan Skema, mereka sekarang dapat melacak perubahan skema.
Pada awalnya beberapa konfigurasi diperlukan. Dalam file konfigurasi untuk cluster tertentu (/etc/cmon.d/cmon_X.cnf), Anda harus menentukan host ClusterControl mana yang harus melacak perubahan dan skema mana yang harus diperiksa.
schema_change_detection_address=10.0.0.126
schema_change_detection_databases=sbtest
Setelah selesai, Anda dapat menjadwalkan laporan untuk dieksekusi secara teratur. Contoh outputnya mungkin seperti di bawah ini:
Seperti yang Anda lihat, dua tabel telah berubah sejak laporan dijalankan sebelumnya. Yang pertama, indeks komposit baru telah dibuat pada kolom (k, c). Di tabel kedua, kolom ditambahkan.
Pada proses selanjutnya kami mendapatkan informasi tentang tabel baru, yang dibuat tanpa indeks atau kunci utama. Dengan menggunakan informasi semacam ini, kita dapat dengan mudah bertindak saat dibutuhkan dan menyelesaikan masalah sebelum benar-benar menjadi pemblokir.