15%

Hemat 15% di Semua Layanan Hosting

Uji kemampuanmu dan dapatkan Diskon pada paket hosting apa saja

Gunakan kode:

Skills
Memulai
08.10.2024

utf8 vs utf8mb4 di MySQL: Panduan Teknis Lengkap

Set karakter utf8 MySQL adalah nama yang menyesatkan — ini bukan implementasi UTF-8 yang sebenarnya. Karakter dikodekan hanya menggunakan 1 hingga 3 byte, yang berarti secara diam-diam membuang atau menolak code point Unicode di atas U+FFFF, termasuk semua emoji dan sebagian besar karakter CJK tambahan. utf8mb4 adalah implementasi UTF-8 yang benar dan lengkap dari MySQL, mendukung 1 hingga 4 byte per karakter dan seluruh rentang Unicode. Untuk database produksi apa pun yang dibuat setelah 2010, utf8mb4 adalah satu-satunya pilihan yang dapat dipertahankan.

Panduan ini menjelaskan secara tepat mengapa perbedaan tersebut penting, di mana desain utf8 asli mengalami kesalahan, cara migrasi dengan aman, dan cara mengonfigurasi MySQL dengan benar di tingkat server, database, tabel, dan koneksi.

Masalah Inti: Mengapa utf8 MySQL Rusak Secara Desain

Standar pengkodean UTF-8 (RFC 3629) mendefinisikan skema lebar variabel yang menggunakan 1 hingga 4 byte untuk merepresentasikan setiap code point Unicode yang valid — lebih dari 1,1 juta karakter yang mungkin. Ketika MySQL memperkenalkan set karakter `utf8` pada versi 4.1, implementasinya sengaja dibatasi hingga 3 byte per karakter. Ini adalah jalan pintas rekayasa yang disengaja, bukan kelalaian.

Pada saat itu, format baris InnoDB memberlakukan batas 767 byte pada prefiks kunci indeks. Mendukung karakter 4-byte akan mengurangi panjang prefiks terindeks maksimum untuk kolom `VARCHAR`, menciptakan masalah kompatibilitas indeks. Batas 3-byte adalah solusi pragmatis yang menjadi kewajiban jangka panjang.

Konsekuensi praktisnya: setiap code point Unicode di Supplementary Multilingual Plane (SMP) — code point U+10000 ke atas — tidak dapat disimpan dalam kolom `utf8`. Ini termasuk:

  • Semua emoji standar (U+1F600 dan seterusnya)
  • Simbol alfanumerik matematika (U+1D400–U+1D7FF)
  • Simbol notasi musik
  • Aksara kuno seperti Linear B, Gothic, dan Cuneiform
  • Ideograf CJK Terpadu Tambahan (U+20000–U+2A6DF)
  • Simbol mata uang tertentu dan operator teknis yang ditambahkan dalam versi Unicode terbaru

Ketika aplikasi mencoba menyisipkan karakter 4-byte ke dalam kolom `utf8`, MySQL mengembalikan kesalahan `Incorrect string value` atau, jika `sql_mode` bersifat permisif, secara diam-diam memotong data. Pemotongan diam-diam bisa dibilang merupakan hasil yang lebih berbahaya — aplikasi Anda tidak menerima kesalahan, tetapi data Anda rusak.

utf8mb4: Implementasi yang Benar

MySQL memperkenalkan utf8mb4 pada versi 5.5.3 (dirilis 2010) khusus untuk mengatasi kekurangan ini. Sufiks `mb4` berarti “multi-byte, maksimum 4 byte.” Ini adalah superset ketat dari `utf8` — setiap karakter yang dapat direpresentasikan dalam `utf8` dapat direpresentasikan secara identik dalam `utf8mb4`. Tidak ada kehilangan data saat bermigrasi dari `utf8` ke `utf8mb4`.

utf8mb4 memetakan langsung ke standar UTF-8 RFC 3629. Ini menangani ruang code Unicode penuh dari U+0000 hingga U+10FFFF tanpa batasan.

utf8 vs utf8mb4: Perbandingan Fitur

Fiturutf8 (MySQL)utf8mb4
Byte per karakter1–31–4
Cakupan UnicodeHanya BMP (U+0000–U+FFFF)Penuh (U+0000–U+10FFFF)
Dukungan EmojiTidakYa
CJK TambahanTidakYa
Sesuai RFC 3629TidakYa
Prefiks indeks maks (InnoDB, halaman 4KB)767 byte767 byte (191 karakter)
Prefiks indeks maks (innodb_large_prefix)3072 byte3072 byte (768 karakter)
Overhead penyimpanan vs latin1Identik untuk ASCIIIdentik untuk ASCII
Direkomendasikan untuk proyek baruTidakYa
Versi MySQL yang memperkenalkan4.15.5.3

Pilihan Collation Dalam utf8mb4

Memilih utf8mb4 sebagai set karakter Anda hanyalah setengah dari keputusan. Collation menentukan bagaimana string dibandingkan, diurutkan, dan diindeks. Collation yang salah menyebabkan perilaku kueri yang halus dan sulit di-debug.

utf8mb4_unicode_ci

Berdasarkan Unicode Collation Algorithm (UCA). Menangani aturan pengurutan khusus bahasa dengan benar. Sedikit lebih lambat dari `utf8mb4_general_ci` karena logika perbandingan yang lebih kompleks, tetapi perbedaan performa tidak signifikan pada perangkat keras modern.

utf8mb4_general_ci

Collation yang disederhanakan yang tidak sepenuhnya mengimplementasikan UCA. Lebih cepat dalam benchmark dari awal 2010-an, tetapi keunggulan kecepatan tidak relevan pada CPU saat ini. Ini menangani beberapa kasus tepi secara tidak benar — misalnya, memperlakukan karakter Jerman tertentu sebagai setara padahal seharusnya tidak. Hindari untuk proyek baru.

utf8mb4_0900_ai_ci

Tersedia di MySQL 8.0+. Berdasarkan Unicode 9.0 dengan perbandingan tidak sensitif aksen (`ai`) dan tidak sensitif huruf besar/kecil (`ci`). Ini adalah default yang direkomendasikan untuk MySQL 8.0 dan yang lebih baru. Ini lebih cepat dari `utf8mb4_unicode_ci` dan lebih akurat.

utf8mb4_bin

Perbandingan biner — sensitif huruf besar/kecil, sensitif aksen, tanpa aturan khusus lokal. Gunakan ketika Anda membutuhkan pencocokan tingkat byte yang tepat, seperti untuk hash kata sandi atau pengenal yang sensitif huruf besar/kecil.

Rekomendasi: Gunakan `utf8mb4_0900_ai_ci` pada MySQL 8.0+. Gunakan `utf8mb4_unicode_ci` pada MySQL 5.7 dan yang lebih lama.

Implikasi Penyimpanan dan Indeks

Kekhawatiran umum saat bermigrasi dari utf8 ke utf8mb4 adalah overhead penyimpanan. Dalam praktiknya, dampaknya minimal:

  • Karakter ASCII (U+0000–U+007F) masih menempati tepat 1 byte di kedua pengkodean.
  • Sebagian besar karakter Latin, Yunani, Sirilik, Arab, dan Ibrani menempati 2 byte di kedua pengkodean.
  • Karakter CJK dalam BMP menempati 3 byte di kedua pengkodean.
  • Hanya karakter tambahan (emoji, CJK tambahan) yang memerlukan 4 byte — dan ini sebelumnya tidak dapat direpresentasikan dalam utf8.

Kekhawatiran indeks yang sebenarnya adalah batas prefiks indeks InnoDB 767 byte pada konfigurasi lama. Dengan utf8mb4, kasus terburuk 4-byte-per-karakter berarti prefiks indeks `VARCHAR` 191 karakter mencapai batas 767 byte. Dengan `utf8`, batas yang sama memungkinkan 255 karakter. Jika Anda memiliki kolom `VARCHAR(255)` dengan indeks kolom penuh, Anda mungkin mengalami kesalahan `Specified key was too long` selama migrasi.

Solusi:

  • Aktifkan `innodb_large_prefix = ON` (MySQL 5.6/5.7) untuk menaikkan batas menjadi 3072 byte.
  • Gunakan `ROW_FORMAT=DYNAMIC` atau `ROW_FORMAT=COMPRESSED` pada tabel yang terpengaruh.
  • Di MySQL 8.0, `innodb_large_prefix` diaktifkan secara default dan parameternya dihapus.
  • Persingkat prefiks indeks: `INDEX (column(191))` alih-alih `INDEX (column(255))`.

Ini adalah titik kegagalan migrasi yang paling umum dan yang paling sering kurang terdokumentasi dalam panduan dasar.

Cara Migrasi Database MySQL dari utf8 ke utf8mb4

Migrasi mudah dilakukan tetapi memerlukan ketelitian. Melewatkan lapisan mana pun — server, database, tabel, atau koneksi — membuat aplikasi Anda diam-diam kembali ke pengkodean lama.

Langkah 1: Cadangkan Database

Jangan pernah memodifikasi pengkodean karakter pada database yang aktif tanpa cadangan yang terverifikasi.

“`bash

mysqldump -u username -p –single-transaction –routines –triggers

database_name > database_backup_$(date +%F).sql

“`

Flag `–single-transaction` memastikan snapshot yang konsisten untuk tabel InnoDB tanpa penguncian. Simpan cadangan di lokasi yang terpisah dari server database sebelum melanjutkan.

Langkah 2: Perbarui Konfigurasi Server MySQL

Edit `/etc/mysql/my.cnf` atau `/etc/mysql/mysql.conf.d/mysqld.cnf` tergantung pada distribusi Anda:

“`ini

[client]

default-character-set = utf8mb4

[mysql]

default-character-set = utf8mb4

[mysqld]

character-set-server = utf8mb4

collation-server = utf8mb4_unicode_ci

For MySQL 5.6/5.7 only — remove on MySQL 8.0

innodb_large_prefix = ON

innodb_file_format = Barracuda

innodb_file_per_table = ON

“`

Mulai ulang MySQL:

“`bash

sudo systemctl restart mysql

“`

Langkah 3: Konversi Database

“`sql

ALTER DATABASE database_name

CHARACTER SET = utf8mb4

COLLATE = utf8mb4_unicode_ci;

“`

Langkah 4: Konversi Semua Tabel

Buat dan jalankan pernyataan `ALTER TABLE` untuk setiap tabel. Menjalankannya secara manual pada skema besar rentan terhadap kesalahan. Gunakan kueri ini untuk menghasilkan pernyataan secara otomatis:

“`sql

SELECT CONCAT(

'ALTER TABLE `', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'

)

FROM information_schema.TABLES

WHERE TABLE_SCHEMA = 'database_name'

AND TABLE_TYPE = 'BASE TABLE';

“`

Jalankan setiap pernyataan yang dihasilkan. Sintaks `CONVERT TO CHARACTER SET` mengubah default tabel dan semua kolom karakter yang ada dalam satu operasi.

Langkah 5: Perbaiki Kesalahan Panjang Indeks

Jika Anda mengalami `Specified key was too long; max key length is 767 bytes`, identifikasi indeks yang bermasalah:

“`sql

— Change full-column index to prefix index

ALTER TABLE table_name DROP INDEX index_name;

ALTER TABLE table_name ADD INDEX index_name (column_name(191));

“`

Khusus untuk database WordPress, kolom `option_name` pada tabel `wp_options` dan kolom `meta_key` pada `wp_postmeta` adalah sumber umum kesalahan ini.

Langkah 6: Verifikasi Konversi

“`sql

— Check server-level variables

SHOW VARIABLES LIKE 'character_set%';

SHOW VARIABLES LIKE 'collation%';

— Check a specific table

SHOW CREATE TABLE table_nameG

— Check all columns in a database

SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME

FROM information_schema.COLUMNS

WHERE TABLE_SCHEMA = 'database_name'

AND DATA_TYPE IN ('char', 'varchar', 'text', 'tinytext', 'mediumtext', 'longtext');

“`

Setiap nilai `CHARACTER_SET_NAME` harus terbaca `utf8mb4`.

Langkah 7: Perbarui String Koneksi Aplikasi

Pengkodean server dan skema tidak berarti apa-apa jika aplikasi Anda terhubung menggunakan set karakter yang salah. Pengkodean tingkat koneksi menggantikan default server.

PHP (PDO):

“`php

$dsn = 'mysql:host=localhost;dbname=database_name;charset=utf8mb4';

$pdo = new PDO($dsn, $user, $pass, [

PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"

]);

“`

PHP (MySQLi):

“`php

$mysqli = new mysqli('localhost', $user, $pass, $db);

$mysqli->set_charset('utf8mb4');

“`

Python (mysql-connector-python):

“`python

cnx = mysql.connector.connect(

host='localhost', user=user, password=pass,

database=db, charset='utf8mb4', collation='utf8mb4_unicode_ci'

)

“`

Node.js (mysql2):

“`javascript

const pool = mysql2.createPool({

host: 'localhost', user: user, password: pass,

database: db, charset: 'utf8mb4'

});

“`

Gagal mengatur charset koneksi adalah alasan paling umum mengapa emoji masih gagal disisipkan setelah migrasi yang seharusnya sudah selesai.

Pertimbangan Khusus WordPress

WordPress telah menggunakan utf8mb4 sebagai set karakter defaultnya sejak versi 4.2 (April 2015). Jika Anda menjalankan instalasi WordPress pada database lama yang belum pernah dimigrasi, file `wp-config.php` mungkin masih berisi:

“`php

define('DB_CHARSET', 'utf8');

“`

Ubah ini menjadi:

“`php

define('DB_CHARSET', 'utf8mb4');

define('DB_COLLATE', 'utf8mb4_unicode_ci');

“`

WordPress juga menyertakan rutinitas peningkatan bawaan (`maybe_convert_table_to_utf8mb4()`) yang berjalan selama pembaruan inti. Namun, rutinitas ini tidak selalu menangkap setiap tabel, terutama yang dibuat oleh plugin. Menjalankan pendekatan `ALTER TABLE` manual yang dijelaskan di atas lebih dapat diandalkan.

Pada lingkungan VPS Hosting dengan akses root, Anda dapat mengotomatiskan seluruh proses ini dengan skrip shell dan menjadwalkannya sebagai cron job satu kali, memberi Anda kendali penuh atas waktu dan pencatatan log.

Pertimbangan Performa

Dampak performa utf8mb4 versus utf8 tidak signifikan untuk sebagian besar beban kerja:

  • Kueri baca: Tidak ada perbedaan yang terukur untuk karakter BMP. Karakter tambahan memerlukan satu byte I/O tambahan, yang diserap oleh caching buffer pool.
  • Kueri tulis: Identik untuk konten ASCII dan BMP. Sedikit lebih tinggi untuk karakter tambahan.
  • Operasi indeks: Panjang prefiks maksimum yang berkurang (191 vs 255 karakter untuk indeks lebar penuh) dapat memengaruhi rencana kueri jika Anda memiliki indeks kolom penuh pada kolom `VARCHAR` yang panjang. Audit indeks Anda sebelum dan sesudah migrasi.
  • Memori: MySQL mengalokasikan buffer lebar tetap untuk operasi string berdasarkan byte maksimum per karakter. Beralih dari utf8 (maks 3 byte) ke utf8mb4 (maks 4 byte) meningkatkan memori yang dialokasikan untuk buffer pengurutan dalam memori dan tabel sementara sekitar 33% untuk operasi yang banyak menggunakan string. Pada Dedicated Server dengan RAM yang cukup, ini tidak berarti apa-apa. Pada lingkungan bersama yang terbatas memori, pantau `sort_buffer_size` dan `tmp_table_size` setelah migrasi.

Kapan utf8 Masih Dapat Diterima

Ada serangkaian alasan yang sempit dan sah untuk mempertahankan `utf8`:

  • Kompatibilitas warisan yang ketat: Aplikasi yang menggunakan ORM atau driver database yang tidak terawat yang tidak dapat menangani karakter 4-byte. Ini adalah masalah utang teknis, bukan alasan untuk mempertahankan utf8 tanpa batas waktu.
  • Database arsip hanya-baca: Jika database tidak akan pernah menerima tulisan baru dan data yang ada tidak mengandung karakter tambahan, migrasi menambah risiko tanpa manfaat.
  • Batasan penyimpanan yang ketat: Dalam kasus ekstrem — sistem tertanam atau lingkungan yang sangat terbatas kapasitasnya — perbedaan penyimpanan marginal mungkin penting. Ini tidak berlaku untuk skenario web hosting standar apa pun.

Dalam setiap kasus lainnya, utf8mb4 adalah pilihan yang tepat. Argumen bahwa utf8 menghemat ruang penyimpanan secara teknis hanya berlaku untuk karakter tambahan, yang tidak dapat direpresentasikan dalam utf8 bagaimanapun juga. Anda tidak menghemat ruang pada data yang tidak dapat Anda simpan.

Memilih Lingkungan Hosting yang Tepat untuk MySQL utf8mb4

Konfigurasi utf8mb4 yang tepat memerlukan akses ke file konfigurasi server MySQL (`my.cnf`). Ini mengecualikan sebagian besar lingkungan shared hosting di mana Anda tidak dapat memodifikasi variabel tingkat server.

Untuk kontrol penuh atas pengkodean karakter MySQL, collation, pengaturan InnoDB, dan parameter koneksi, Anda memerlukan paket VPS Hosting dengan akses root atau Dedicated Server. Keduanya memberi Anda akses langsung ke `/etc/mysql/my.cnf`, kemampuan untuk memulai ulang layanan MySQL, dan kebebasan untuk mengonfigurasi `innodb_large_prefix`, `ROW_FORMAT`, dan parameter lain yang memengaruhi keberhasilan migrasi utf8mb4.

Jika Anda mengelola beberapa database atau situs klien, VPS dengan cPanel menyediakan antarmuka grafis untuk manajemen database sambil mempertahankan akses server yang mendasarinya yang diperlukan untuk konfigurasi set karakter. Untuk tim yang lebih menyukai fleksibilitas baris perintah dengan panel yang ringan, VPS Control Panels menawarkan beberapa alternatif yang sesuai dengan alur kerja operasional yang berbeda.

Untuk proyek yang juga memerlukan transmisi data yang aman, memasangkan migrasi database Anda dengan SSL Certificate yang dikonfigurasi dengan benar memastikan bahwa data yang dikodekan utf8mb4 dilindungi saat transit, bukan hanya saat diam.

Daftar Periksa Keputusan Teknis

Gunakan daftar periksa ini sebelum dan sesudah migrasi utf8 ke utf8mb4:

Pra-migrasi:

  • [ ] Cadangan `mysqldump` penuh terverifikasi dan dapat dipulihkan
  • [ ] Versi MySQL dikonfirmasi (5.5.3+ diperlukan untuk utf8mb4)
  • [ ] Status `innodb_large_prefix` diperiksa (aktifkan jika pada MySQL 5.6/5.7)
  • [ ] Semua kolom `VARCHAR(255)` dengan indeks kolom penuh diidentifikasi
  • [ ] Kode charset koneksi aplikasi ditinjau dan diperbarui
  • [ ] Jendela pemeliharaan dijadwalkan untuk database produksi

Pasca-migrasi:

  • [ ] `SHOW VARIABLES LIKE 'character_set%'` menampilkan `utf8mb4` di tingkat server
  • [ ] `SHOW CREATE TABLE` mengonfirmasi `utf8mb4` pada semua tabel yang dikonversi
  • [ ] Kueri `information_schema.COLUMNS` mengonfirmasi tidak ada kolom `utf8` yang tersisa
  • [ ] `SET NAMES utf8mb4` tingkat aplikasi atau yang setara dikonfirmasi dalam kode koneksi
  • [ ] Uji penyisipan emoji berhasil pada tabel yang representatif
  • [ ] Baseline performa kueri dibandingkan dengan metrik pra-migrasi
  • [ ] Panjang indeks diverifikasi — tidak ada pemotongan diam-diam pada nilai terindeks yang panjang

FAQ

Apakah migrasi dari utf8 ke utf8mb4 menyebabkan kehilangan data?

Tidak. utf8mb4 adalah superset ketat dari utf8 MySQL. Setiap karakter yang disimpan dalam kolom utf8 dapat direpresentasikan secara identik dalam utf8mb4. Migrasi tidak merusak data yang ada. Satu-satunya risiko adalah kesalahan panjang indeks pada kolom `VARCHAR(255)` dengan indeks kolom penuh, yang harus diselesaikan dengan mempersingkat prefiks indeks.

Mengapa emoji masih gagal disisipkan setelah saya mengonversi tabel ke utf8mb4?

Penyebab paling umum adalah charset koneksi aplikasi. Jika kode PHP, Python, atau Node.js Anda terhubung tanpa secara eksplisit menentukan `utf8mb4`, MySQL menggunakan default `character_set_client` server untuk sesi tersebut. Tambahkan `SET NAMES utf8mb4` atau parameter charset yang setara ke konfigurasi koneksi Anda.

Apa perbedaan antara utf8mb4_unicode_ci dan utf8mb4_0900_ai_ci?

`utf8mb4_unicode_ci` didasarkan pada aturan collation Unicode 4.0 dan merupakan pilihan standar untuk MySQL 5.7. `utf8mb4_0900_ai_ci` didasarkan pada Unicode 9.0, merupakan default di MySQL 8.0, dan lebih cepat serta lebih akurat secara linguistik. Gunakan `utf8mb4_0900_ai_ci` pada MySQL 8.0+ untuk proyek baru.

Apakah beralih ke utf8mb4 akan meningkatkan ukuran penyimpanan database saya secara signifikan?

Dalam praktiknya, tidak. ASCII dan sebagian besar karakter BMP menggunakan jumlah byte yang sama di kedua pengkodean. Hanya karakter tambahan (emoji, CJK tambahan) yang menggunakan 4 byte — dan itu sebelumnya tidak dapat direpresentasikan dalam utf8. Overhead memori untuk buffer pengurutan meningkat sekitar 33% untuk operasi yang banyak menggunakan string, tetapi ini tidak signifikan pada server modern apa pun.

Bisakah saya mengonfigurasi utf8mb4 pada shared hosting?

Sebagian. Anda dapat mengatur set karakter di tingkat database dan tabel menggunakan pernyataan SQL `ALTER`, dan Anda dapat menentukan charset dalam string koneksi aplikasi Anda. Namun, Anda tidak dapat memodifikasi `my.cnf` atau memulai ulang MySQL pada shared hosting. Default tingkat server akan tetap tidak berubah, yang berarti database baru yang dibuat melalui panel hosting mungkin default ke utf8. Konfigurasi utf8mb4 penuh memerlukan VPS atau dedicated server dengan akses root.

15%

Hemat 15% di Semua Layanan Hosting

Uji kemampuanmu dan dapatkan Diskon pada paket hosting apa saja

Gunakan kode:

Skills
Memulai