Bermigrasi dari MySQL ke Spanner

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

Batasan migrasi

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

Prosedur tersimpan dan pemicu

Spanner tidak mendukung kode pengguna yang berjalan di tingkat database, sehingga sebagai bagian dari migrasi, logika bisnis yang diterapkan oleh prosedur dan pemicu yang disimpan di tingkat 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 yang dibalik bit-nya (GoogleSQL, PostgreSQL), yang menghasilkan nilai yang didistribusikan secara merata di seluruh ruang angka 64-bit positif. Anda dapat menggunakan angka ini untuk menghindari masalah hotspotting.

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

Kontrol akses

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

Batasan validasi data

Spanner mendukung sekumpulan batasan validasi data terbatas di lapisan database. Jika memerlukan batasan data yang lebih kompleks, Anda harus menerapkan batasan tersebut di lapisan aplikasi.

Tabel berikut membahas jenis batasan yang biasa 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 mungkin untuk tabel yang diselingi; jika tidak, diterapkan di lapisan aplikasi
Pemeriksaan dan validasi nilai melalui batasan CHECK Lihat Membuat dan mengelola batasan pemeriksaan.
Pemeriksaan dan validasi nilai melalui pemicu Diimplementasikan di lapisan aplikasi

Kolom yang dihasilkan

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

Kolom yang dihasilkan ditentukan sebagai bagian dari definisi kolom selama pernyataan Bahasa Definisi Data (DDL) CREATE TABLE atau ALTER TABLE. 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 dengan kolom lain tabel.

Fungsi SQL, ekspresi pembuatan, dapat menyertakan 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 dihasilkan.

Jenis data yang didukung

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

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

Jenis data MySQL Padanan Spanner Catatan
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 presisi dan skala hingga total 65 digit, seperti yang ditentukan dalam deklarasi kolom. Jenis data NUMERIC Spanner mendukung presisi hingga 38 digit dan skala 9 digit desimal.
Jika Anda memerlukan presisi yang lebih tinggi, lihat Menyimpan data numerik presisi arbitrer untuk mekanisme alternatif.
BIT BYTES
DATE DATE Spanner dan MySQL menggunakan format 'yyyy-mm-dd' untuk tanggal, sehingga tidak diperlukan transformasi. Fungsi SQL disediakan untuk mengonversi tanggal ke string berformat.
DATETIME, TIMESTAMP TIMESTAMP Spanner menyimpan waktu secara independen 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 di seluruh bagian.
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 Google Cloud alternatif 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 di aplikasi
SET ARRAY<STRING> Validasi nilai elemen SET harus dilakukan di 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 Google Cloud alternatif 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 proses migrasi Anda adalah:

  1. Konversikan skema dan model data Anda.
  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 ke Spanner menggunakan Dataflow.
  5. Pertahankan konsistensi antara kedua database selama migrasi.
  6. Migrasikan aplikasi Anda dari MySQL.

Langkah 1: Konversi database dan skema Anda

Anda mengonversi skema yang ada ke skema Spanner untuk menyimpan data. Untuk mempermudah modifikasi aplikasi, pastikan skema yang dikonversi cocok dengan skema MySQL yang ada sebanyak mungkin. Namun, karena perbedaan fitur, beberapa perubahan mungkin diperlukan.

Menggunakan praktik terbaik dalam desain skema dapat membantu Anda meningkatkan throughput dan mengurangi hot spot di 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 mengidentifikasi setiap baris dalam tabel secara unik, dan Spanner menggunakan kunci utama untuk mengurutkan baris tabel. Karena Spanner sangat terdistribusi, Anda harus memilih teknik pembuatan kunci utama yang diskalakan dengan baik sesuai dengan pertumbuhan data Anda. Untuk informasi selengkapnya, lihat strategi migrasi kunci utama yang kami rekomendasikan.

Perhatikan bahwa setelah menetapkan 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 Skema dan model data - kunci utama.

Menggabungkan tabel

Spanner memiliki fitur yang memungkinkan Anda menentukan dua tabel sebagai memiliki hubungan induk-turunan 1-banyak. Fitur ini menyisipkan baris data turunan di samping baris induknya dalam penyimpanan, yang secara efektif melakukan pra-penggabungan tabel 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 saat baris induk dihapus: semua baris turunan dihapus, atau penghapusan baris induk diblokir saat baris turunan ada.

Berikut adalah contoh pembuatan tabel Albums yang diselingi dalam tabel Penyanyi 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 seperti kunci utama tabel. Hal ini juga berarti bahwa indeks memiliki jaminan konsistensi yang sama dengan tabel Spanner.

Pencarian nilai menggunakan indeks sekunder secara efektif sama dengan kueri dengan join tabel. Anda dapat meningkatkan performa kueri menggunakan indeks dengan menyimpan salinan nilai kolom tabel asli di indeks sekunder menggunakan klausa STORING, sehingga menjadi indeks cakupan.

Pengoptimal kueri Spanner hanya otomatis menggunakan indeks sekunder jika 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 penambahannya menjadi rata-rata tiga per hari. Untuk panduan selengkapnya tentang 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 (mengambil keuntungan dari data yang telah digabungkan sebelumnya). Untuk informasi selengkapnya, lihat bagian Subkueri dalam dokumentasi.

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

Langkah 3: Migrasikan aplikasi Anda untuk menggunakan Spanner

Spanner menyediakan kumpulan Library klien untuk berbagai bahasa, dan kemampuan untuk membaca dan menulis data menggunakan panggilan API khusus Spanner, serta menggunakan pernyataan kueri SQL dan Data Modification Language (DML). Menggunakan panggilan API mungkin lebih cepat untuk beberapa kueri, seperti pembacaan baris langsung berdasarkan kunci, karena pernyataan SQL tidak perlu diterjemahkan.

Spanner menyediakan driver JDBC untuk aplikasi Java.

Sebagai bagian dari proses migrasi, fitur yang tidak tersedia di Spanner seperti yang disebutkan di atas harus diterapkan di aplikasi. Misalnya, pemicu untuk memverifikasi nilai data dan memperbarui tabel terkait harus diterapkan dalam aplikasi menggunakan transaksi baca/tulis untuk membaca baris yang ada, memverifikasi batasan, lalu menulis baris yang 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, dengan Anda membaca versi data yang konsisten:

  • pada waktu yang tepat di masa lalu (hingga 1 jam yang lalu).
  • pada masa mendatang (saat pembacaan akan diblokir hingga waktu tersebut tiba).
  • dengan jumlah keusangan terbatas yang dapat diterima, yang akan menampilkan tampilan yang konsisten hingga beberapa waktu sebelumnya tanpa perlu memeriksa apakah data berikutnya tersedia di replika lain. Hal ini dapat memberikan manfaat performa, tetapi dengan mengorbankan data yang mungkin sudah tidak berlaku.

Langkah 4: Transfer data Anda dari MySQL ke Spanner

Untuk mentransfer data dari MySQL ke Spanner, Anda harus mengekspor database MySQL 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 ke dalam file XML yang terbentuk dengan baik. Atau, Anda dapat menggunakan pernyataan SQL SELECT ... INTO OUTFILE untuk 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 menonaktifkan database sehingga database tetap dalam status yang konsisten untuk diekspor.

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

Impor massal ke Spanner

Karena skema database mungkin berbeda antara MySQL dan Spanner, Anda mungkin perlu membuat 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 ekstrak, transformasi, dan pemuatan (ETL) terdistribusi Google Cloud. Layanan ini menyediakan platform untuk menjalankan pipeline data yang ditulis menggunakan Apache Beam SDK guna membaca dan memproses data dalam jumlah besar secara paralel di beberapa mesin.

Apache Beam SDK mengharuskan Anda menulis program Java sederhana untuk menetapkan pembacaan, transformasi, dan penulisan data. Konektor Beam ada untuk Cloud Storage dan Spanner, sehingga 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 interleaved induk-turunan dalam skema Spanner, perhatikan dalam proses impor bahwa baris induk dibuat sebelum baris turunan. Kode pipeline impor Spanner menangani hal ini dengan mengimpor semua data untuk tabel tingkat root terlebih dahulu, lalu semua tabel turunan tingkat 1, lalu semua tabel turunan tingkat 2, dan seterusnya.

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

Langkah 5: Menjaga konsistensi antara kedua database

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

Ada berbagai metode untuk menjaga sinkronisasi dua database Anda, termasuk pengambilan data perubahan, dan menerapkan pembaruan serentak di aplikasi.

Pengambilan data perubahan

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

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

Update simultan ke kedua database dari aplikasi

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

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

Memverifikasi konsistensi data

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

Anda dapat menggunakan Dataflow untuk melakukan perbandingan mendetail pada set data besar menggunakan Transformasi join. Transformasi ini menggunakan 2 set data dengan kunci, dan mencocokkan nilai menurut 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 tepercaya aplikasi Anda

Jika yakin dengan migrasi data, Anda dapat mengalihkan aplikasi untuk menggunakan Spanner sebagai sumber tepercaya. Jika Anda terus menulis kembali perubahan ke database MySQL, database MySQL akan terus diperbarui, sehingga memberikan jalur rollback jika masalah muncul.

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

Mengekspor dan mengimpor database Spanner

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

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

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

Langkah selanjutnya