Hướng Dẫn Thay Đổi Bộ Ký Tự MySQL: Chuyển Sang utf8mb4 (Sửa Lỗi Mojibake)

目次

1. Giới thiệu

Tại sao bạn có thể cần thay đổi bộ ký tự MySQL

Một bộ ký tự cơ sở dữ liệu là một cài đặt quan trọng quyết định cách dữ liệu văn bản được mã hoá và xử lý để lưu trữ. Trong MySQL, bộ ký tự mặc định thường là latin1, điều này có thể gây ra vấn đề khi làm việc với tiếng Nhật hoặc các ký tự đặc biệt khác. Đặc biệt trong quá trình di chuyển dữ liệu hoặc chuẩn hoá hệ thống, việc chuyển sang một bộ ký tự phù hợp trở nên thiết yếu.

Các vấn đề thường gặp và nguyên nhân của chúng

Các vấn đề điển hình liên quan đến bộ ký tự MySQL bao gồm những điều sau.

  1. Mojibake (ký tự rối)
  • utf8latin1 được trộn lẫn trong cùng một môi trường
  • Cài đặt bộ ký tự của client và server không khớp
  1. Vấn đề khi tìm kiếm
  • Do sự khác nhau về collation, kết quả tìm kiếm không như mong đợi
  • Thứ tự sắp xếp khác với dự kiến
  1. Vấn đề trong quá trình di chuyển dữ liệu
  • Emoji và các ký tự đặc biệt không thể lưu vì không sử dụng utf8mb4
  • Chuyển đổi bộ ký tự không được xử lý đúng trong quá trình xuất/nhập

Mục tiêu và cấu trúc bài viết

Bài viết này cung cấp giải thích toàn diện về việc thay đổi bộ ký tự MySQL, từ các khái niệm cơ bản đến cách thay đổi cài đặtkhắc phục sự cố.

Đề cương

  1. Kiến thức cơ bản về bộ ký tự MySQL
  2. Cách kiểm tra bộ ký tự hiện tại
  3. Cách thay đổi bộ ký tự MySQL
  4. Khắc phục sự cố sau khi thay đổi
  5. Cách thay đổi bộ ký tự ảnh hưởng đến hiệu năng
  6. Các cài đặt đề xuất (thực tiễn tốt nhất)
  7. Câu hỏi thường gặp (FAQ)

Bằng cách đọc hướng dẫn này, bạn sẽ hiểu sâu hơn về bộ ký tự MySQL và có thể chọn lựa cài đặt phù hợp và tránh các vấn đề phổ biến.

2. Bộ ký tự MySQL là gì? Hiểu các khái niệm cơ bản

Bộ ký tự là gì?

Một bộ ký tự (Character Set) là một tập hợp các quy tắc dùng để lưu trữ và xử lý ký tự dưới dạng dữ liệu số. Ví dụ, khi lưu ký tự Nhật “あ”, UTF-8 biểu diễn nó dưới dạng dãy byte E3 81 82, trong khi Shift_JIS dùng 82 A0.

Trong MySQL, bạn có thể chỉ định các bộ ký tự khác nhau ở mức cơ sở dữ liệu hoặc bảng. Bằng cách chọn bộ ký tự phù hợp, bạn có thể ngăn ngừa mojibake và làm cho việc quốc tế hoá trở nên suôn sẻ hơn.

Các bộ ký tự phổ biến

Character SetCharacteristicsUse Case
utf8UTF-8 up to 3 bytesDoes not support some special characters (such as emoji)
utf8mb4UTF-8 up to 4 bytesSupports emoji and special characters (recommended)
latin1ASCII-compatibleUsed in older systems

Collation là gì?

Collation là tập hợp các quy tắc dùng để so sánh và sắp xếp dữ liệu trong một bộ ký tự. Ví dụ, nó xác định liệu “A” và “a” có được coi là cùng một ký tự và cách thứ tự được quyết định như thế nào.

Collation thường dùng

CollationDescription
utf8_general_ciCase-insensitive, suitable for general use
utf8_unicode_ciUnicode-based collation (recommended)
utf8mb4_binBinary comparison (use when exact matches are required)

Sự khác nhau giữa utf8utf8mb4

utf8 của MySQL thực tế chỉ có thể lưu tối đa 3 byte cho mỗi ký tự, vì vậy không thể xử lý một số ký tự đặc biệt (như emoji hoặc một số ký tự CJK mở rộng). Ngược lại, utf8mb4 hỗ trợ tới 4 byte cho mỗi ký tự, vì vậy các ứng dụng hiện đại được khuyến nghị sử dụng utf8mb4.

Character SetMax BytesEmoji SupportRecommendation
utf83 bytes❌ Not supported❌ Not recommended
utf8mb44 bytes✅ Supported✅ Recommended

Tại sao bạn nên chuyển từ utf8 sang utf8mb4

  1. Tương thích trong tương lai : Các hệ thống hiện đại ngày càng chuẩn hoá trên utf8mb4.
  2. Lưu ký tự đặc biệt và emoji : Với utf8mb4, bạn có thể an toàn xử lý dữ liệu trong các bài đăng SNS và ứng dụng nhắn tin.
  3. Quốc tế hoá : Đối với các hệ thống đa ngôn ngữ, nó giảm nguy cơ mojibake.

Tóm tắt

  • Bộ ký tự quyết định cách dữ liệu được lưu trữ và xử lý.
  • Collation quyết định cách ký tự được so sánh.
  • utf8 của MySQL bị giới hạn ở 3 byte, vì vậy utf8mb4 được khuyến nghị.
  • utf8mb4_unicode_ci là một collation thường được đề xuất cho mục đích chung.

3. Cách kiểm tra bộ ký tự hiện tại

Trước khi thay đổi bộ ký tự MySQL, việc kiểm tra các cài đặt hiện tại là rất quan trọng.
Vì bộ ký tự có thể được đặt ở nhiều cấp độ (cơ sở dữ liệu, bảng, cột), bạn cần hiểu chính xác nơi cần thực hiện thay đổi.

Cách kiểm tra bộ ký tự hiện tại

Kiểm tra bộ ký tự toàn máy chủ MySQL

Đầu tiên, kiểm tra bộ ký tự mặc định và cài đặt collation cho toàn bộ máy chủ MySQL.

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

Ví dụ đầu ra:

+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                        |
+--------------------------+----------------------------+

Kiểm tra Bộ ký tự cho mỗi Cơ sở dữ liệu

Để kiểm tra bộ ký tự cho một cơ sở dữ liệu cụ thể, hãy sử dụng truy vấn sau.

SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'database_name';

Ví dụ đầu ra

+----------------+----------------------+----------------------+
| SCHEMA_NAME    | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+----------------+----------------------+----------------------+
| my_database   | utf8mb4               | utf8mb4_unicode_ci   |
+----------------+----------------------+----------------------+

Kiểm tra Bộ ký tự của Bảng

Đây là cách kiểm tra bộ ký tự cho một bảng cụ thể.

SHOW CREATE TABLE table_name;

Ví dụ đầu ra

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;

Các điểm kiểm tra

  • DEFAULT CHARSET=latin1 → Không phải utf8mb4, vì vậy cần thay đổi
  • COLLATE=latin1_swedish_ci → Chuyển sang utf8mb4_unicode_ci thường là phù hợp hơn

Kiểm tra Bộ ký tự của Cột

Để kiểm tra bộ ký tự ở mức cột, chạy câu lệnh SQL sau.

SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME 
FROM information_schema.COLUMNS 
WHERE TABLE_SCHEMA = 'database_name' 
AND TABLE_NAME = 'table_name';

Ví dụ đầu ra

+-------------+--------------------+----------------------+
| COLUMN_NAME | CHARACTER_SET_NAME | COLLATION_NAME       |
+-------------+--------------------+----------------------+
| name        | latin1             | latin1_swedish_ci    |
| email       | utf8mb4            | utf8mb4_unicode_ci   |
+-------------+--------------------+----------------------+

Trong ví dụ này, cột name sử dụng latin1, vì vậy nên thay đổi nó sang utf8mb4.

Tóm tắt

  • Bộ ký tự MySQL được cấu hình ở nhiều cấp độ (máy chủ, cơ sở dữ liệu, bảng, cột).
  • Bằng cách kiểm tra bộ ký tự ở mỗi cấp độ, bạn có thể áp dụng các thay đổi phù hợp.
  • Sử dụng các lệnh như SHOW VARIABLESSHOW CREATE TABLE để hiểu đầy đủ cấu hình hiện tại.

4. Cách Thay Đổi Bộ Ký Tự MySQL

Bằng cách thay đổi bộ ký tự MySQL một cách thích hợp, bạn có thể ngăn hiện tượng mojibake và hỗ trợ dữ liệu đa ngôn ngữ một cách mượt mà hơn.
Trong phần này, chúng tôi giải thích cách cập nhật cài đặt ở mỗi cấp độ: toàn máy chủ, cơ sở dữ liệu, bảng và cột.

Thay Đổi Bộ Ký Tự Mặc Định Toàn Máy Chủ

Để thay đổi bộ ký tự mặc định toàn máy chủ, bạn cần chỉnh sửa tệp cấu hình MySQL (my.cnf hoặc my.ini).

Các bước

  1. Mở tệp cấu hình
  • Trên Linux: bash sudo nano /etc/mysql/my.cnf
  • Trên Windows: wp:list /wp:list

    • Mở C:\ProgramData\MySQL\MySQL Server X.X\my.ini
  1. Thêm hoặc thay đổi cài đặt bộ ký tự Thêm hoặc cập nhật các dòng sau dưới phần mysqld.
    [mysqld]
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    
  1. Khởi động lại MySQL
    sudo systemctl restart mysql
    

Trên Windows:

net stop MySQL && net start MySQL
  1. Xác minh thay đổi
    SHOW VARIABLES LIKE 'character_set_server';
    

Thay đổi Bộ ký tự ở mức Cơ sở dữ liệu

ALTER DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Xác minh thay đổi

SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME 
FROM information_schema.SCHEMATA 
WHERE SCHEMA_NAME = 'mydatabase';

Thay đổi Bộ ký tự ở mức Bảng

ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Xác minh thay đổi

SHOW CREATE TABLE users;

Thay đổi Bộ ký tự ở mức Cột

ALTER TABLE users MODIFY COLUMN name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Xác minh thay đổi

SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME 
FROM information_schema.COLUMNS 
WHERE TABLE_SCHEMA = 'mydatabase' 
AND TABLE_NAME = 'users';

Xác minh sau khi thay đổi và Tầm quan trọng của Sao lưu

Để bảo toàn tính toàn vẹn dữ liệu sau khi thay đổi bộ ký tự, hãy thực hiện các bước sau.

Sao lưu dữ liệu của bạn

mysqldump -u root -p --default-character-set=utf8mb4 mydatabase > backup.sql

Kiểm tra lại các cài đặt

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
SHOW CREATE TABLE users;

Chèn và hiển thị dữ liệu thử nghiệm

INSERT INTO users (name, email) VALUES ('Test User', 'test@example.com');
SELECT * FROM users;

Tóm tắt

  • Thay đổi bộ ký tự trên toàn máy chủ : Chỉnh sửa my.cnf và đặt character-set-server=utf8mb4
  • Thay đổi bộ ký tự của cơ sở dữ liệu : ALTER DATABASE mydatabase CHARACTER SET utf8mb4
  • Thay đổi bộ ký tự của bảng : ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4
  • Thay đổi bộ ký tự của cột : ALTER TABLE users MODIFY COLUMN name VARCHAR(255) CHARACTER SET utf8mb4
  • Sau khi thay đổi, luôn luôn xác minh cài đặt và kiểm tra dữ liệu của bạn

5. Khắc phục sự cố sau khi thay đổi bộ ký tự

Sau khi thay đổi bộ ký tự của MySQL, bạn có thể gặp các trường hợp hệ thống không hoạt động đúng hoặc dữ liệu đã lưu bị lỗi. Trong phần này, chúng tôi giải thích các vấn đề phổ biến và cách khắc phục chúng một cách chi tiết.

Nguyên nhân gây Mojibake và Cách khắc phục

Nếu mojibake xảy ra sau khi thay đổi bộ ký tự, các nguyên nhân sau thường gặp.

CauseHow to CheckSolution
The client character set setting differsSHOW VARIABLES LIKE 'character_set_client';Run SET NAMES utf8mb4;
Existing data was stored using a different encodingSELECT HEX(column_name) FROM table_name;Use CONVERT() or re-export the data
The connection encoding is not correctConnect with mysql --default-character-set=utf8mb4Adjust the client-side character set configuration
Application settings (PHP/Python, etc.) are incorrectmysqli_set_charset($conn, 'utf8mb4');Standardize the application’s character set settings

Sửa #1: Đặt bộ ký tự client đúng cách

SET NAMES utf8mb4;

Sửa #2: Chuyển đổi dữ liệu hiện có một cách chính xác

UPDATE users SET name = CONVERT(CAST(CONVERT(name USING latin1) AS BINARY) USING utf8mb4);

Lưu ý khi chuyển đổi từ latin1 sang utf8mb4

Quy trình an toàn

  1. Sao lưu dữ liệu hiện tại
    mysqldump -u root -p --default-character-set=latin1 mydatabase > backup.sql
    
  1. Thay đổi bộ ký tự của cơ sở dữ liệu
    ALTER DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
  1. Thay đổi bộ ký tự của bảng
    ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
  1. Nhập lại dữ liệu
    mysql -u root -p --default-character-set=utf8mb4 mydatabase < backup.sql
    

Dữ liệu không thể tìm kiếm sau khi thay đổi

Trường hợp #1: Tìm kiếm LIKE không hoạt động

SELECT * FROM users WHERE name COLLATE utf8mb4_unicode_ci LIKE '%Tanaka%';

Trường hợp #2: Thứ tự sắp xếp đã thay đổi

SELECT * FROM users ORDER BY BINARY name;

Các biện pháp phía ứng dụng

Đối với PHP

mysqli_set_charset($conn, 'utf8mb4');

Đối với Python (MySQL Connector)

import mysql.connector

conn = mysql.connector.connect(
    host="localhost",
    user="root",
    password="password",
    database="mydatabase",
    charset="utf8mb4"
)

For Node.js (MySQL2)

const mysql = require('mysql2');

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'mydatabase',
  charset: 'utf8mb4'
});

Summary

  • Post-change issues generally fall into three categories: client settings, data conversion, and application settings.
  • To prevent mojibake, standardize the client character set using SET NAMES utf8mb4.
  • Watch for LIKE search and sort order changes, and specify COLLATE when needed.
  • Set utf8mb4 in your application as well to avoid encoding mismatches.

6. How Character Set Changes Affect Performance

When changing the MySQL character set to utf8mb4, there are several performance considerations, such as increased storage usage and index limitations.
In this section, we explain the impact and the best countermeasures.

Increased Storage Usage

Compared to MySQL’s utf8, utf8mb4 can use up to 4 bytes per character,
so the overall table size may increase.

Max bytes per character by character set

Character SetMax Bytes per Character
latin11 byte
utf83 bytes
utf8mb44 bytes

For example, with utf8, VARCHAR(255) is up to 765 bytes (255×3),
but with utf8mb4, it becomes up to 1020 bytes (255×4).

Countermeasure

ALTER TABLE posts MODIFY COLUMN title VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Increased Index Size

MySQL enforces a maximum index key length.
After switching to utf8mb4, index entries become larger, and you may hit the limit—making indexes unusable.

Check index impact

SHOW INDEX FROM users;

Example error

ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

Countermeasure

ALTER TABLE users MODIFY COLUMN email VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Impact on Query Performance

Changing the character set to utf8mb4 may affect query execution speed.

Operations that may be affected

  • LIKE searches over large datasets
  • ORDER BY processing
  • JOIN query performance

Countermeasure

CREATE INDEX idx_name ON users(name(100));

Memory Usage and Buffer Tuning

With utf8mb4, memory usage may increase.

Recommended settings

[mysqld]
innodb_buffer_pool_size = 1G
query_cache_size = 128M

Summary

  • Switching to utf8mb4 increases storage usage.
  • Index sizes increase and may exceed limits.
  • Query performance can be affected.
  • Because memory usage may increase, buffer sizes may need tuning.

7. Recommended Settings (Best Practices)

By setting MySQL character sets appropriately, you can maintain data integrity while optimizing performance.
In this section, we present recommended MySQL character set configurations and explain key points for an optimal setup.

Recommended MySQL Character Set Configuration

ItemRecommended SettingReason
Character Setutf8mb4Supports all Unicode characters including emoji and special characters
Collationutf8mb4_unicode_ciCase-insensitive and suitable for multilingual systems
Storage EngineInnoDBGood balance of performance and consistency
Indexed string lengthVARCHAR(191)Avoids exceeding MySQL index limits

Recommended my.cnf Settings

1. MySQL Server Character Set Settings

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init-connect='SET NAMES utf8mb4'
skip-character-set-client-handshake
innodb_large_prefix = ON
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_buffer_pool_size = 1G
query_cache_size = 128M

2. Client-Side Character Set Settings

[client]
default-character-set = utf8mb4

Recommended Database Settings

CREATE DATABASE mydatabase DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

To change an existing database character set:

ALTER DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Recommended Table Settings

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
  email VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Thay đổi bộ ký tự cho các bảng hiện có

ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Sự khác nhau giữa utf8mb4_general_ciutf8mb4_unicode_ci

CollationCharacteristicsUse Case
utf8mb4_general_ciFaster comparisons, but less accuratePerformance-focused systems
utf8mb4_unicode_ciUnicode-standard, more accurate comparisonsGeneral-purpose use (recommended)

Nếu bạn cần hỗ trợ đa ngôn ngữ hoặc sắp xếp chính xác, hãy chọn utf8mb4_unicode_ci.

Tối ưu hoá chỉ mục

CREATE FULLTEXT INDEX idx_fulltext ON articles(content);

Tóm tắt

  • Kết hợp utf8mb4 + utf8mb4_unicode_ci được khuyến nghị.
  • Chuẩn hoá cài đặt máy chủ (my.cnf) và bộ ký tự kết nối.
  • Rõ ràng chỉ định utf8mb4 ở mức cơ sở dữ liệu, bảng và cột.
  • Sử dụng VARCHAR(191) để tránh giới hạn độ dài khóa chỉ mục.
  • Sử dụng utf8mb4_unicode_ci để so sánh chính xác.

8. FAQ

Dưới đây là các câu hỏi thực tế thường gặp về việc thay đổi bộ ký tự MySQL.
Chúng tôi cũng đề cập đến cách xử lý lỗicách chọn cài đặt tốt nhất.

Sự khác nhau giữa utf8utf8mb4 là gì?

SHOW VARIABLES LIKE 'character_set_server';

Việc thay đổi bộ ký tự MySQL có gây mất dữ liệu không?

mysqldump -u root -p --default-character-set=utf8mb4 mydatabase > backup.sql

Làm sao để khắc phục hiện tượng mojibake nếu xảy ra?

UPDATE users SET name = CONVERT(CAST(CONVERT(name USING latin1) AS BINARY) USING utf8mb4);

Rủi ro khi chuyển từ latin1 sang utf8mb4 là gì?

ALTER DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Việc chuyển sang utf8mb4 có ảnh hưởng đến hiệu năng không?

ALTER TABLE users MODIFY COLUMN email VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Nên sử dụng cái nào: utf8mb4_general_ci hay utf8mb4_unicode_ci?

CollationCharacteristicsUse Case
utf8mb4_general_ciFaster comparisons, but less accuratePerformance-focused systems
utf8mb4_unicode_ciUnicode-standard, accurate comparisonsGeneral-purpose use (recommended)

Các truy vấn sẽ chậm hơn sau khi chuyển sang utf8mb4 không?

CREATE FULLTEXT INDEX idx_fulltext ON articles(content);

Tóm tắt

utf8mb4 được khuyến nghị. utf8 không được khuyến nghị do các hạn chế của nó.
Trước khi thực hiện thay đổi, luôn kiểm tra cài đặt bằng SHOW VARIABLES.
Sử dụng quy trình xuất/nhập để ngăn ngừa mojibake.
Xem xét các giới hạn chỉ mục và sử dụng VARCHAR(191) khi cần.
Để tối ưu hiệu năng, thêm các chỉ mục phù hợp.

Ghi chú cuối cùng

Thay đổi bộ ký tự MySQL không chỉ là một điều chỉnh cấu hình đơn giản—đó là một nhiệm vụ quan trọng có thể ảnh hưởng đến tính toàn vẹn dữ liệu và hiệu năng.
Bằng cách tuân thủ các cài đặt và quy trình đúng, bạn có thể di chuyển sang utf8mb4 một cách an toàn và hiệu quả.

🔹 Hãy làm theo các bước trong bài viết này và cấu hình bộ ký tự của bạn một cách chính xác! 🔹