WPML

Bộ ký tự và đối chiếu trong MySQL là gì?

Khi WordPress lưu trữ nội dung trang web của bạn trong cơ sở dữ liệu (như bài viết, tiêu đề, chuỗi văn bản đã dịch, v.v.), nó sử dụng một bộ ký tự để biểu diễn các ký tự và một đối chiếu để xác định cách các ký tự đó được so sánh và sắp xếp.

Bộ ký tự (Charset)
Xác định cách các ký tự được lưu trữ trong cơ sở dữ liệu — về cơ bản, byte nào đại diện cho ký tự nào.
Đối chiếu (Collation)
Xác định các quy tắc để so sánh các ký tự đó (ví dụ: phân biệt chữ hoa chữ thường, phân biệt dấu và thứ tự sắp xếp).

Tại sao điều này lại quan trọng đối với các trang web đa ngôn ngữ

WPML hỗ trợ nội dung đa ngôn ngữ, thường bao gồm:

  • Các ký tự đặc biệt (ví dụ: ñ, é, ö)
  • Các chữ viết không phải hệ Latinh (ví dụ: tiếng Ả Rập, tiếng Nhật, tiếng Trung, tiếng Do Thái)
  • Biểu tượng cảm xúc và ký hiệu (🎉, ✔️, v.v.)

Nhiều ký tự trong số này yêu cầu nhiều hơn 3 byte để được lưu trữ chính xác. Nếu cơ sở dữ liệu của bạn sử dụng một đối chiếu không tương thích, các ký tự có thể bị mất, bị thay thế bằng ? hoặc gây ra lỗi cơ sở dữ liệu (ví dụ: “Incorrect string value”).

Đó là lý do tại sao chúng tôi đề xuất mạnh mẽ việc sử dụng đối chiếu hỗ trợ các ký tự Unicode 4-byte.

Đề xuất của chúng tôi

Sử dụng bộ ký tự utf8mb4đối chiếu tương thích với Unicode, chẳng hạn như:

  • utf8mb4_unicode_ci – tương thích rộng rãi, mặc định tốt
  • utf8mb4_unicode_520_ci – xử lý Unicode tốt hơn trên MySQL 5.6+
  • utf8mb4_general_ci – nhanh hơn một chút, so sánh Unicode kém chính xác hơn
  • utf8mb4_bin – phân biệt chữ hoa chữ thường và dấu (so sánh nhị phân)

Tất cả các đối chiếu này đều an toàn để sử dụng với WPML.


Quan trọng: Bộ ký tự utf8 cũ trong MySQL chỉ hỗ trợ tối đa 3 byte cho mỗi ký tự. Nó không thể xử lý một số ký tự như biểu tượng cảm xúc hoặc một số chữ tượng hình. Tránh sử dụng nó cho nội dung đa ngôn ngữ.

Mặc định trong MySQL là gì?

Phiên bản MySQLBộ ký tự mặc địnhĐối chiếu mặc địnhTương thích Unicode
< 5.5latin1latin1_swedish_ciKhông
5.5.xutf8utf8_general_ciKhông
5.7+utf8mb4utf8mb4_general_ci / utf8mb4_unicode_ci
8.0+utf8mb4utf8mb4_0900_ai_ci

WordPress có thể không phải lúc nào cũng tuân theo mặc định của MySQL — nó có thể ghi đè mặc định đó thông qua cấu hình hoặc quá trình di chuyển dữ liệu.

Cài đặt bộ ký tự và đối chiếu cho các trang web mới

Để đảm bảo WordPress tạo các bảng mới với bộ ký tự và đối chiếu chính xác, hãy xác định các nội dung sau trong tệp wp-config.php của bạn:

define( 'DB_CHARSET', 'utf8mb4' ); // If you have utf8 that's fine, WP will automatically map it as utf8mb4
define( 'DB_COLLATE', 'utf8mb4_unicode_ci' );

Điều này sẽ áp dụng cho các bản cài đặt mới và các bảng mới được tạo.

Kiểm tra bộ ký tự và đối chiếu cho các trang web và bảng hiện có

Dưới đây là cách kiểm tra bộ ký tự và đối chiếu trên các trang web hiện có của bạn.

Tùy chọn 1 phpMyAdmin

  1. Truy cập cơ sở dữ liệu trang web của bạn.
  2. Kiểm tra cột “Collation” bên cạnh mỗi bảng.
  3. Nhấp vào một bảng để xem đối chiếu riêng lẻ của từng cột.

Tùy chọn 2 WP-CLI

bash

wp db query "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.tables WHERE table_schema = 'your_db_name';"

Bạn cũng có thể kiểm tra từng cột riêng lẻ:

bash

wp db query "SHOW FULL COLUMNS FROM wp_posts;"

Nếu bạn thấy đối chiếu bắt đầu bằng utf8mb4_ thì nó đã sẵn sàng để hỗ trợ tất cả các loại unicode và chữ tượng hình 4-byte. Bộ ký tự cũng ổn.

Nếu bạn thấy thông tin khác, ví dụ utf8_* thì bạn cần thay đổi nó.

Vui lòng lưu ý rằng đối chiếu có thể khác nhau ở mỗi cột.

Cập nhật bộ ký tự và đối chiếu cho các bảng và cột hiện có

Việc cập nhật các hằng số DB_CHARSET và DB_COLLATE trong tệp wp-config.php của bạn chỉ ảnh hưởng đến các bảng mới. Để áp dụng các thay đổi cho các bảng và cột hiện có, bạn phải chuyển đổi chúng theo cách thủ công bằng SQL.

Chúng tôi cũng khuyên bạn nên cập nhật đối chiếu MySQL mặc định của cơ sở dữ liệu bằng lệnh sau:

ALTER DATABASE your_database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Luôn bắt đầu bằng việc sao lưu

Trước khi chạy bất kỳ truy vấn chuyển đổi nào:

  • Xuất cơ sở dữ liệu của bạn bằng phpMyAdmin hoặc mysqldump
  • Lưu trữ an toàn để phòng trường hợp có sự cố xảy ra

Cảnh báo: Cập nhật đối chiếu có thể thất bại trong chế độ Strict Mode

Khi cập nhật đối chiếu của toàn bộ bảng (hoặc cơ sở dữ liệu), MySQL có thể xây dựng lại các bảng và xác thực lại tất cả các giá trị mặc định của cột — bao gồm cả các cột không liên quan như DATETIME. Nếu cơ sở dữ liệu của bạn đang chạy ở chế độ SQL nghiêm ngặt (STRICT_TRANS_TABLES, NO_ZERO_DATE), các cột có giá trị mặc định như ‘0000-00-00 00:00:00’ sẽ gây ra các lỗi như:

#1067 - Invalid default value.

Chế độ Strict Mode là gì?

Chế độ Strict Mode kiểm soát cách MySQL xử lý các giá trị không hợp lệ hoặc bị thiếu khi dữ liệu được thêm hoặc cập nhật vào cơ sở dữ liệu. Một giá trị có thể không hợp lệ vì một vài lý do. Ví dụ: nó có thể sai kiểu dữ liệu đối với cột hoặc có thể nằm ngoài phạm vi.

Bạn có thể tìm thông tin về các loại xác thực dữ liệu khác nhau cho chế độ Strict Mode trong tài liệu MySQL.

Cách chế độ Strict Mode ảnh hưởng đến cơ sở dữ liệu trang web WordPress

Theo mặc định, WordPress sử dụng ‘0000-00-00 00:00:00’ làm mặc định cho một số cột datetime, điều này không được chấp nhận bởi chế độ NO_ZERO_DATE strict mode.

Lưu ý rằng các giá trị mặc định này được cho phép trong quá trình tạo bảng ban đầu (ví dụ: trong khi thiết lập WordPress), nhưng sẽ thất bại khi thực hiện các thao tác ALTER trong các môi trường nghiêm ngặt.

Cách kiểm tra xem chế độ Strict Mode có được bật hay không

Chạy lệnh sau:

SELECT @@SESSION.sql_mode, @@GLOBAL.sql_mode;

Tìm kiếm:

  • STRICT_TRANS_TABLES
  • STRICT_ALL_TABLES
  • NO_ZERO_DATE

Nếu bạn tìm thấy bất kỳ mục nào trong số này, chế độ Strict Mode đang được bật.

Để tránh lỗi trong quá trình cập nhật bộ ký tự và đối chiếu, bạn chỉ cần tắt chế độ NO_ZERO_DATE strict mode.

Cách tiến hành an toàn

Thực hiện một trong các cách sau để tiến hành an toàn:

1. Tránh thay đổi các cột và bảng trừ khi đối chiếu thực sự cần thay đổi.

2. Tạm thời tắt chế độ Strict Mode chỉ cho phiên làm việc hiện tại trong khi chạy các truy vấn chuyển đổi. Bạn có thể làm điều này bằng cách sử dụng lệnh sau:

SET SESSION sql_mode = REPLACE(@@sql_mode, 'NO_ZERO_DATE', '');

Lưu ý: có những kế hoạch trong tương lai cho MySQL để hợp nhất các chế độ Strict Mode.

Trong trường hợp có các vấn đề khác đặc thù với dữ liệu của bạn, bạn có thể muốn tắt bất kỳ chế độ Strict Mode nào bằng lệnh sau:

SET SESSION sql_mode = '';

Các truy vấn để chuyển đổi dữ liệu

Chuyển đổi toàn bộ cơ sở dữ liệu

Phần sau đây tạo ra một truy vấn ALTER TABLE cho mỗi bảng trong cơ sở dữ liệu của bạn:

SELECT CONCAT(
  'ALTER TABLE `', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'
) AS query
  FROM INFORMATION_SCHEMA.TABLES
  WHERE TABLE_SCHEMA = 'your_database_name';

Chạy các truy vấn kết quả trong phpMyAdmin hoặc sao chép và dán vào MySQL CLI / WP-CLI.

Điều này đảm bảo tất cả các bảng trong cơ sở dữ liệu của bạn áp dụng bộ ký tự và đối chiếu mới.

Chuyển đổi một bảng cụ thể Tùy chọn/Phụ trợ
ALTER TABLE wp_posts 
  CONVERT TO CHARACTER SET utf8mb4 
  COLLATE utf8mb4_unicode_ci;

Điều này cập nhật tất cả các cột văn bản trong bảng wp_posts để sử dụng utf8mb4 và đối chiếu được chỉ định.


Chuyển đổi một cột cụ thể Tùy chọn/Phụ trợ
ALTER TABLE wp_posts 
  CHANGE post_title post_title TEXT 
  CHARACTER SET utf8mb4 
  COLLATE utf8mb4_unicode_ci;

Lưu ý:

  • Bạn phải khai báo lại đầy đủ cột (kiểu, tên) trong CHANGE.
  • Đảm bảo kiểu cột khớp với kiểu hiện có.

Các lỗi phổ biến khi chuyển đổi

Dưới đây là hai lỗi phổ biến mà bạn có thể gặp phải khi chuyển đổi các bảng và cột.

Bộ ký tự và đối chiếu không khớp
-- INVALID: utf8 collation with utf8mb4 charset
ALTER TABLE wp_posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8_general_ci;
-- Error: COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4'

Giải pháp:

  • Sử dụng một đối chiếu phù hợp: utf8mb4_*

Giới hạn độ dài khóa chỉ mục
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

Trong một số cấu hình, đặc biệt là đối với các phiên bản MySQL dưới 5.7, độ dài khóa chỉ mục tối đa có thể bị vượt quá khi thêm một byte cho mỗi ký tự.

Giải pháp:

  • Rút ngắn VARCHAR(255) được lập chỉ mục thành VARCHAR(191) nếu cần
  • Hoặc nâng cấp lên MySQL 5.7+ và đảm bảo innodb_large_prefix được bật

Tóm tắt

  • Sử dụng bộ ký tự utf8mb4 để hỗ trợ Unicode đầy đủ
  • Sử dụng các đối chiếu tương thích: utf8mb4_unicode_ci, utf8mb4_0900_ai_ci, v.v.
  • Cập nhật wp-config.php cho các bảng mới
  • Chạy các quá trình di chuyển SQL để sửa các bảng hiện có
  • Không bao giờ trộn lẫn các bộ ký tự và đối chiếu — MySQL sẽ từ chối hoặc làm hỏng chúng.