Bermigrasi dari MySQL ke Spanner

Artikel ini menjelaskan cara memigrasikan database Pemrosesan Transaksi Online (OLTP) Anda dari MySQL ke Spanner.

Batasan migrasi

Spanner menggunakan konsep tertentu secara berbeda dengan alat pengelolaan database perusahaan lainnya, sehingga Anda mungkin perlu menyesuaikan arsitektur aplikasi untuk memanfaatkan kemampuannya secara maksimal. Anda mungkin juga perlu melengkapi Spanner dengan layanan lain dari Google Cloud untuk memenuhi kebutuhan Anda.

Prosedur dan pemicu tersimpan

Spanner tidak mendukung menjalankan kode pengguna di level database. Jadi, sebagai bagian dari migrasi, logika bisnis yang diimplementasikan oleh prosedur dan pemicu tersimpan level database harus dipindahkan ke aplikasi.

Urutan

Spanner merekomendasikan penggunaan UUID Versi 4 sebagai metode default untuk menghasilkan nilai kunci utama. Fungsi GENERATE_UUID() (GoogleSQL, PostgreSQL) menampilkan nilai UUID Versi 4 yang direpresentasikan sebagai jenis STRING.

Jika Anda perlu menghasilkan nilai bilangan bulat, Spanner mendukung urutan positif terbalik bit (GoogleSQL, PostgreSQL), yang menghasilkan nilai yang didistribusikan secara merata di seluruh ruang angka 64-bit positif. Anda dapat menggunakan angka-angka ini untuk menghindari masalah hotspotting.

Untuk mengetahui informasi selengkapnya, lihat strategi nilai default utama utama.

Kontrol akses

Spanner mendukung kontrol akses terperinci di tingkat tabel dan kolom. Kontrol akses yang mendetail untuk tampilan tidak didukung. Untuk informasi selengkapnya, lihat Tentang kontrol akses terperinci.

Batasan validasi data

Spanner mendukung serangkaian batasan validasi data yang terbatas di lapisan database. Jika memerlukan batasan data yang lebih kompleks, Anda harus mengimplementasikannya di lapisan aplikasi.

Tabel berikut membahas jenis batasan yang umum ditemukan di database MySQL, dan cara menerapkannya dengan Spanner.

Batasan Implementasi dengan Spanner
Bukan null Batasan kolom NOT NULL
Unik Indeks sekunder dengan batasan UNIQUE
Foreign key (untuk tabel normal) Lihat Membuat dan mengelola hubungan kunci asing.
Tindakan ON DELETE/ON UPDATE kunci asing Hanya memungkinkan untuk tabel sisipan; jika tidak, akan diterapkan di lapisan aplikasi
Pemeriksaan nilai dan validasi melalui batasan CHECK Lihat Membuat dan mengelola batasan pemeriksaan.
Pemeriksaan nilai dan validasi melalui pemicu Diimplementasikan di lapisan aplikasi

Kolom yang dihasilkan

Spanner mendukung kolom yang dihasilkan, yang nilai kolomnya akan selalu dihasilkan oleh fungsi yang diberikan sebagai bagian dari definisi tabel. Seperti di MySQL, kolom yang dihasilkan tidak dapat ditetapkan secara jelas ke nilai yang diberikan dalam pernyataan DML.

Kolom yang dihasilkan ditentukan sebagai bagian dari definisi kolom selama pernyataan CREATE TABLE atau ALTER TABLE Data Definition Language (DDL). Kata kunci AS diikuti dengan fungsi SQL yang valid dan kata kunci akhiran yang diperlukan STORED. Kata kunci STORED adalah bagian dari spesifikasi ANSI SQL, dan menunjukkan bahwa hasil fungsi akan disimpan bersama kolom lainnya dalam tabel.

Fungsi SQL, yang merupakan ekspresi pembuatan, dapat mencakup ekspresi, fungsi, dan operator deterministik apa pun, serta dapat digunakan dalam indeks sekunder atau digunakan sebagai kunci asing.

Pelajari lebih lanjut cara mengelola jenis kolom ini dengan meninjau Membuat dan mengelola kolom yang dibuat.

Jenis data yang didukung

MySQL dan Spanner mendukung kumpulan jenis data yang berbeda. Tabel berikut mencantumkan jenis data MySQL dan padanannya di Spanner. Untuk definisi mendetail setiap jenis data Spanner, lihat Jenis data.

Anda mungkin perlu mentransformasi data lebih lanjut seperti yang dijelaskan di kolom Catatan agar data MySQL sesuai dengan database Spanner. Misalnya, Anda dapat menyimpan BLOB besar sebagai objek dalam bucket Cloud Storage, bukan dalam database, lalu menyimpan referensi URI ke objek Cloud Storage dalam database sebagai STRING.

Jenis data MySQL Setara dengan Spanner Notes
INTEGER, INT, BIGINT MEDIUMINT, SMALLINT INT64
TINYINT, BOOL, BOOLEAN BOOL, INT64 Nilai TINYINT(1) digunakan untuk merepresentasikan nilai boolean 'true' (bukan nol) atau 'false' (0).
FLOAT, DOUBLE FLOAT64
DECIMAL, NUMERIC NUMERIC, STRING Di MySQL,jenis data NUMERIC dan DECIMAL mendukung hingga total 65 digit presisi dan skala, seperti yang ditentukan dalam deklarasi kolom. Jenis data NUMERIC Spanner mendukung presisi hingga 38 digit dan 9 digit desimal.
Jika Anda memerlukan presisi yang lebih baik, lihat Menyimpan data numerik presisi arbitrer untuk mekanisme alternatif.
BIT BYTES
DATE DATE Baik Spanner maupun MySQL menggunakan format 'yyyy-mm-dd' untuk tanggal, sehingga transformasi tidak diperlukan. Fungsi SQL disediakan untuk mengonversi tanggal menjadi string yang diformat.
DATETIME, TIMESTAMP TIMESTAMP Spanner menyimpan waktu secara terpisah dari zona waktu. Jika perlu menyimpan zona waktu, Anda harus menggunakan kolom STRING terpisah. Fungsi SQL disediakan untuk mengonversi stempel waktu menjadi string berformat menggunakan zona waktu.
CHAR, VARCHAR STRING Catatan: Spanner menggunakan string Unicode secara keseluruhan.
VARCHAR mendukung panjang maksimum 65.535 byte, sedangkan Spanner mendukung hingga 2.621.440 karakter.
BINARY, VARBINARY, BLOB, TINYBLOB BYTES Objek kecil (kurang dari 10 MiB) dapat disimpan sebagai BYTES. Pertimbangkan untuk menggunakan penawaran alternatif Google Cloud, seperti Cloud Storage, untuk menyimpan objek yang lebih besar
TEXT, TINYTEXT, ENUM STRING Nilai TEXT kecil (kurang dari 10 MiB) dapat disimpan sebagai STRING. Pertimbangkan untuk menggunakan penawaran Google Cloud alternatif seperti Cloud Storage untuk mendukung nilai TEXT yang lebih besar.
ENUM STRING Validasi nilai ENUM harus dilakukan dalam aplikasi
SET ARRAY<STRING> Validasi nilai elemen SET harus dilakukan dalam aplikasi
LONGBLOB, MEDIUMBLOB BYTES atau STRING yang berisi URI ke objek. Objek kecil (kurang dari 10 MiB) dapat disimpan sebagai BYTES. Pertimbangkan untuk menggunakan penawaran Google Cloud alternatif seperti Cloud Storage untuk menyimpan objek yang lebih besar.
LONGTEXT, MEDIUMTEXT STRING (berisi data atau URI ke objek eksternal) Objek kecil (kurang dari 2.621.440 karakter) dapat disimpan sebagai STRING. Pertimbangkan untuk menggunakan penawaran alternatif Google Cloud, seperti Cloud Storage, untuk menyimpan objek yang lebih besar
JSON JSON String JSON kecil (kurang dari 2.621.440 karakter) dapat disimpan sebagai JSON. Pertimbangkan untuk menggunakan penawaran Google Cloud alternatif seperti Cloud Storage untuk menyimpan objek yang lebih besar.
GEOMETRY, POINT, LINESTRING, POLYGON, MULTIPOINT, MULTIPOLYGON, GEOMETRYCOLLECTION Spanner tidak mendukung jenis data Geospasial. Anda harus menyimpan data ini menggunakan jenis data standar, dan menerapkan logika penelusuran/pemfilteran di lapisan aplikasi.

Proses migrasi

Linimasa keseluruhan dari proses migrasi Anda adalah:

  1. Mengonversi skema dan model data.
  2. Menerjemahkan kueri SQL apa pun.
  3. Migrasikan aplikasi Anda untuk menggunakan Spanner selain MySQL.
  4. Mengekspor data secara massal dari MySQL dan mengimpor data tersebut ke Spanner menggunakan Dataflow.
  5. Pertahankan konsistensi di antara kedua database selama migrasi.
  6. Migrasikan aplikasi Anda dari MySQL.

Langkah 1: Konversi database dan skema Anda

Anda mengonversi skema yang ada menjadi skema Spanner untuk menyimpan data Anda. Agar modifikasi aplikasi menjadi lebih sederhana, pastikan skema yang dikonversi cocok dengan skema MySQL yang ada semirip mungkin. Namun, karena perbedaan fitur, beberapa perubahan mungkin diperlukan.

Menggunakan praktik terbaik dalam desain skema dapat membantu Anda meningkatkan throughput dan mengurangi hot spot dalam database Spanner.

Kunci utama

Di Spanner, setiap tabel yang harus menyimpan lebih dari satu baris harus memiliki kunci utama yang terdiri dari satu atau beberapa kolom tabel. Kunci utama tabel Anda secara unik mengidentifikasi setiap baris dalam tabel, dan Spanner menggunakan kunci utama untuk mengurutkan baris tabel. Karena Spanner sangat terdistribusi, Anda harus memilih teknik pembuatan kunci utama yang diskalakan dengan baik seiring dengan pertumbuhan data Anda. Untuk informasi selengkapnya, lihat strategi migrasi utama yang kami rekomendasikan.

Perhatikan bahwa setelah menentukan kunci utama, Anda tidak dapat menambahkan atau menghapus kolom kunci utama, atau mengubah nilai kunci utama nanti tanpa menghapus dan membuat ulang tabel. Untuk mengetahui informasi selengkapnya tentang cara menetapkan kunci utama, lihat Model data dan skema - kunci utama.

Menyisipkan tabel

Spanner memiliki fitur yang memungkinkan Anda menentukan dua tabel sebagai hubungan induk-turunan 1-banyak. Fitur ini menyisipkan baris data turunan di samping baris induknya dalam penyimpanan, sehingga menggabungkan tabel terlebih dahulu dan meningkatkan efisiensi pengambilan data saat induk dan turunan dikueri bersama.

Kunci utama tabel turunan harus dimulai dengan kolom kunci utama dari tabel induk. Dari perspektif baris turunan, kunci utama baris induk disebut sebagai kunci asing. Anda dapat menentukan hingga 6 tingkat hubungan induk-turunan.

Anda dapat menentukan tindakan saat penghapusan untuk tabel turunan guna menentukan apa yang terjadi jika baris induk dihapus: semua baris turunan akan dihapus, atau penghapusan baris induk diblokir saat baris turunan ada.

Berikut contoh pembuatan tabel Album yang disisipi di tabel Singers induk yang ditentukan sebelumnya:

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId)
INTERLEAVE IN PARENT (Singers)
ON DELETE CASCADE;

Membuat indeks sekunder

Anda juga dapat membuat indeks sekunder untuk mengindeks data dalam tabel di luar kunci utama. Spanner menerapkan indeks sekunder dengan cara yang sama seperti tabel, sehingga nilai kolom yang akan digunakan sebagai kunci indeks akan memiliki batasan yang sama dengan kunci utama tabel. Ini juga berarti bahwa indeks memiliki jaminan konsistensi yang sama dengan tabel Spanner.

Pencarian nilai menggunakan indeks sekunder pada dasarnya sama dengan kueri dengan gabungan tabel. Anda dapat meningkatkan performa kueri menggunakan indeks dengan menyimpan salinan nilai kolom tabel asli dalam indeks sekunder menggunakan klausa STORING, sehingga menjadikannya indeks cakupan.

Pengoptimal kueri Spanner hanya secara otomatis menggunakan indeks sekunder saat indeks itu sendiri menyimpan semua kolom yang dikueri (kueri yang tercakup). Untuk memaksa penggunaan indeks saat membuat kueri kolom dalam tabel asli, Anda harus menggunakan perintah Force INDEX dalam pernyataan SQL, misalnya:

SELECT *
FROM MyTable@{FORCE_INDEX=MyTableIndex}
WHERE IndexedColumn=@value

Indeks dapat digunakan untuk menerapkan nilai unik dalam kolom tabel, dengan menentukan indeks UNIQUE di kolom tersebut. Penambahan nilai duplikat akan dicegah oleh indeks.

Berikut adalah contoh pernyataan DDL yang membuat indeks sekunder untuk tabel Album:

CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);

Jika Anda membuat indeks tambahan setelah data dimuat, pengisian indeks mungkin memerlukan waktu beberapa saat. Sebaiknya batasi frekuensi penambahan jumlah resource menjadi rata-rata tiga per hari. Untuk panduan lebih lanjut mengenai cara membuat indeks sekunder, lihat Indeks sekunder. Untuk mengetahui informasi selengkapnya tentang batasan pembuatan indeks, lihat Pembaruan skema.

Langkah 2: Terjemahkan kueri SQL apa pun

Spanner menggunakan dialek SQL ANSI 2011 dengan ekstensi, dan memiliki banyak fungsi dan operator untuk membantu menerjemahkan dan menggabungkan data Anda. Setiap kueri SQL yang menggunakan dialek, fungsi, dan jenis khusus MySQL harus dikonversi agar kompatibel dengan Spanner.

Meskipun Spanner tidak mendukung data terstruktur sebagai definisi kolom, Anda dapat menggunakan data terstruktur dalam kueri SQL menggunakan jenis ARRAY<> dan STRUCT<>. Misalnya, Anda dapat menulis kueri yang menampilkan semua Album untuk artis menggunakan ARRAY dari STRUCT (memanfaatkan data yang telah digabungkan). Untuk mengetahui informasi lebih lanjut, lihat bagian Subquery pada dokumentasi.

Kueri SQL dapat dibuat profilnya menggunakan halaman Spanner Studio di Google Cloud Console untuk menjalankan kueri. Secara umum, kueri yang melakukan pemindaian tabel penuh pada tabel besar sangat mahal, dan harus digunakan secara hemat. Untuk mengetahui informasi selengkapnya tentang cara mengoptimalkan kueri SQL, lihat dokumentasi praktik terbaik SQL.

Langkah 3: Migrasikan aplikasi Anda untuk menggunakan Spanner

Spanner menyediakan sekumpulan Library klien untuk berbagai bahasa, dan kemampuan untuk membaca dan menulis data menggunakan panggilan API khusus Spanner, serta dengan menggunakan Kueri SQL dan pernyataan Bahasa Modifikasi Data (DML). Penggunaan panggilan API mungkin lebih cepat untuk beberapa kueri, seperti pembacaan baris langsung berdasarkan kunci, karena pernyataan SQL tidak harus diterjemahkan.

Anda juga dapat menggunakan driver Java Database Connectivity (JDBC) untuk terhubung ke Spanner, yang memanfaatkan alat dan infrastruktur yang ada yang tidak memiliki integrasi native.

Sebagai bagian dari proses migrasi, fitur yang tidak tersedia di Spanner seperti yang disebutkan di atas harus diterapkan ke aplikasi. Misalnya, pemicu untuk memverifikasi nilai data dan memperbarui tabel terkait harus diterapkan di aplikasi menggunakan transaksi baca/tulis untuk membaca baris yang ada, memverifikasi batasan, lalu menulis baris yang telah diperbarui ke kedua tabel.

Spanner menawarkan transaksi baca/tulis dan hanya baca, yang memastikan konsistensi eksternal data Anda. Selain itu, transaksi baca dapat menerapkan Batas stempel waktu, di mana Anda membaca versi data yang konsisten:

  • pada waktu yang sama persis sebelumnya (hingga 1 jam yang lalu).
  • di masa mendatang (ketika pembacaan akan diblokir hingga waktu tersebut tiba).
  • dengan jumlah penghentian yang dibatasi dalam jumlah yang dapat diterima, yang akan menampilkan tampilan yang konsisten hingga beberapa waktu di masa lalu tanpa perlu memeriksa apakah data selanjutnya tersedia di replika lain. Hal ini dapat memberikan manfaat performa dengan mengorbankan data yang mungkin tidak berlaku.

Langkah 4: Transfer data dari MySQL ke Spanner

Untuk mentransfer data dari MySQL ke Spanner, Anda harus mengekspor database MySQL Anda ke format file portabel—misalnya, XML—lalu mengimpor data tersebut ke Spanner menggunakan Dataflow.

mentransfer data dari MySQL ke Spanner

Ekspor massal dari MySQL

Alat mysqldump yang disertakan dengan MySQL dapat mengekspor seluruh database menjadi file XML yang diformat dengan baik. Atau, Anda dapat menggunakan pernyataan SQL SELECT ... INTO OUTFILE guna membuat file CSV untuk setiap tabel. Namun, pendekatan ini memiliki kelemahan bahwa hanya satu tabel yang dapat diekspor dalam satu waktu, yang berarti Anda harus menjeda aplikasi atau melakukan quiesce database sehingga database tetap dalam status konsisten untuk ekspor.

Setelah mengekspor file data ini, sebaiknya upload file tersebut ke bucket Cloud Storage agar dapat diakses untuk diimpor.

Mengimpor secara massal ke Spanner

Karena skema database antara MySQL dan Spanner mungkin berbeda, Anda mungkin perlu menjadikan beberapa konversi data sebagai bagian dari proses impor. Cara termudah untuk melakukan konversi data ini dan mengimpor data ke Spanner adalah dengan menggunakan Dataflow. Dataflow adalah layanan Google Cloud Distribute, Transform, and Load (ETL). Library ini menyediakan platform untuk menjalankan pipeline data yang ditulis menggunakan Apache Beam SDK agar dapat membaca dan memproses data dalam jumlah besar secara paralel di beberapa mesin.

Apache Beam SDK mengharuskan Anda menulis program Java sederhana untuk menyetel pembacaan, transformasi, dan penulisan data. Konektor Beam tersedia untuk Cloud Storage dan Spanner, jadi satu-satunya kode yang perlu Anda tulis adalah transformasi data itu sendiri.

Untuk contoh pipeline sederhana yang membaca dari file CSV dan menulis ke Spanner, lihat repositori kode contoh.

Jika Anda menggunakan tabel sisipan induk-turunan dalam skema Spanner, perhatikan proses impor bahwa baris induk dibuat sebelum baris turunan. Kode pipeline impor Spanner menangani hal ini dengan mengimpor semua data untuk tabel level root terlebih dahulu, lalu semua tabel turunan level 1, lalu semua tabel turunan level 2, dan seterusnya.

Anda dapat langsung menggunakan pipeline impor Spanner untuk mengimpor data secara massal, tetapi pendekatan ini mengharuskan data Anda ada di file Avro menggunakan skema yang benar.

Langkah 5: Pertahankan konsistensi di antara kedua database

Banyak aplikasi memiliki persyaratan ketersediaan yang membuat aplikasi tidak dapat disimpan secara offline selama waktu yang diperlukan untuk mengekspor dan mengimpor data Anda. Oleh karena itu, saat mentransfer data ke Spanner, aplikasi Anda akan terus mengubah database yang ada. Jadi, Anda perlu menduplikasi update ke database Spanner saat aplikasi sedang berjalan.

Ada berbagai metode untuk menjaga sinkronisasi kedua database Anda, termasuk pengambilan data perubahan, dan menerapkan update simultan dalam aplikasi.

Ubah pengambilan data

MySQL tidak memiliki utilitas pengambilan data perubahan (CDC) native. Namun, ada berbagai project open source yang dapat menerima binlog MySQL dan mengonversinya menjadi aliran CDC. Misalnya, daemon Maxwell dapat menyediakan aliran data CDC untuk database Anda.

Anda dapat menulis aplikasi yang berlangganan aliran data ini dan menerapkan modifikasi yang sama (tentunya setelah konversi data) ke database Spanner Anda.

Update simultan pada kedua database dari aplikasi

Metode alternatifnya adalah dengan memodifikasi aplikasi Anda untuk melakukan penulisan ke kedua database. Satu database (awalnya MySQL) akan dianggap sebagai sumber kebenaran, dan setelah setiap penulisan database, seluruh baris akan dibaca, dikonversi, dan ditulis ke database Spanner. Dengan cara ini, aplikasi terus-menerus menimpa baris Spanner dengan data terbaru.

Setelah yakin bahwa semua data telah ditransfer dengan benar, Anda dapat mengalihkan sumber tepercaya ke database Spanner. Mekanisme ini menyediakan jalur rollback jika ditemukan masalah saat beralih ke Spanner.

Memverifikasi konsistensi data

Saat data mengalir ke database Spanner, Anda dapat secara berkala menjalankan perbandingan antara data Spanner dan data MySQL untuk memastikan data tersebut konsisten. Anda dapat memvalidasi konsistensi dengan membuat kueri kedua sumber data dan membandingkan hasilnya.

Anda dapat menggunakan Dataflow untuk melakukan perbandingan terperinci atas set data besar menggunakan Transformasi Join. Transformasi ini menggunakan 2 set data dengan kunci, dan mencocokkan nilai berdasarkan kunci. Nilai yang cocok kemudian dapat dibandingkan untuk kesetaraan. Anda dapat menjalankan verifikasi ini secara rutin hingga tingkat konsistensinya sesuai dengan persyaratan bisnis Anda.

Langkah 6: Beralih ke Spanner sebagai sumber kebenaran aplikasi Anda

Setelah yakin dengan migrasi data, Anda dapat mengalihkan aplikasi untuk menggunakan Spanner sebagai sumber kebenaran. Jika Anda terus menulis kembali perubahan pada database MySQL, ini akan membuat database MySQL tetap terbaru, sehingga memberikan jalur rollback jika muncul masalah.

Terakhir, Anda dapat menonaktifkan dan menghapus kode pembaruan database MySQL serta mematikan database MySQL yang kini sudah tidak digunakan lagi.

Mengekspor dan mengimpor database Spanner

Secara opsional, Anda dapat mengekspor tabel dari Spanner ke bucket Cloud Storage menggunakan template Dataflow untuk melakukan ekspor. Folder yang dihasilkan berisi kumpulan file Avro dan file manifes JSON yang berisi tabel yang Anda ekspor. File-file ini dapat memiliki berbagai tujuan, termasuk:

  • Mencadangkan database Anda untuk mematuhi kebijakan retensi data atau pemulihan dari bencana.
  • Mengimpor file Avro ke penawaran Google Cloud lainnya seperti BigQuery.

Untuk mengetahui informasi selengkapnya tentang proses ekspor dan impor, lihat Mengekspor database dan Mengimpor database.

Langkah selanjutnya