本節說明在 utf8mb3
和 utf8mb4
字元集之間轉換字元資料時可能遇到的問題。
本討論主要集中在 utf8mb3
和 utf8mb4
之間的轉換,但類似的原則適用於在 ucs2
字元集和 utf16
或 utf32
等字元集之間轉換。
utf8mb3
和 utf8mb4
字元集的差異如下
utf8mb3
僅支援基本多文種平面 (BMP) 中的字元。utf8mb4
額外支援位於 BMP 之外的補充字元。utf8mb3
每個字元最多使用三個位元組。utf8mb4
每個字元最多使用四個位元組。
本討論引用 utf8mb3
和 utf8mb4
字元集名稱,以明確表示參考 3 位元組和 4 位元組 UTF-8 字元集資料。
從 utf8mb3
轉換為 utf8mb4
的一個優點是,這使應用程式能夠使用補充字元。一個缺點是,這可能會增加資料儲存空間的需求。
就資料表內容而言,從 utf8mb3
轉換為 utf8mb4
不會產生任何問題
對於 BMP 字元,
utf8mb4
和utf8mb3
具有相同的儲存特性:相同的程式碼值、相同的編碼、相同的長度。對於補充字元,
utf8mb4
需要四個位元組才能儲存它,而utf8mb3
根本無法儲存該字元。將utf8mb3
資料行轉換為utf8mb4
時,您無需擔心轉換補充字元,因為沒有補充字元。
就資料表結構而言,以下是主要的潛在不相容之處
因此,若要將資料表從 utf8mb3
轉換為 utf8mb4
,可能需要變更某些資料行或索引定義。
可以使用 ALTER TABLE
將資料表從 utf8mb3
轉換為 utf8mb4
。假設資料表具有以下定義
CREATE TABLE t1 (
col1 CHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL,
col2 CHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL
) CHARACTER SET utf8mb3;
以下陳述式會將 t1
轉換為使用 utf8mb4
ALTER TABLE t1
DEFAULT CHARACTER SET utf8mb4,
MODIFY col1 CHAR(10)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
MODIFY col2 CHAR(10)
CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;
從 utf8mb3
轉換為 utf8mb4
時的問題是,資料行或索引鍵的最大長度在 位元組 方面未變更。因此,在 字元 方面會較小,因為字元的最大長度為四個位元組而不是三個位元組。對於 CHAR
、VARCHAR
和 TEXT
資料類型,在轉換 MySQL 資料表時請注意這些問題
檢查
utf8mb3
資料行的所有定義,並確保它們不超過儲存引擎的最大長度。檢查
utf8mb3
資料行的所有索引,並確保它們不超過儲存引擎的最大長度。有時,最大值可能會因儲存引擎的增強而變更。
如果套用上述條件,您必須縮短資料行或索引的定義長度,或繼續使用 utf8mb3
而不是 utf8mb4
。
以下是一些可能需要結構變更的範例
一個
TINYTEXT
欄位最多可容納 255 個位元組,因此最多可容納 85 個 3 位元組或 63 個 4 位元組的字元。假設您有一個使用utf8mb3
的TINYTEXT
欄位,但必須能夠包含超過 63 個字元。除非您同時將資料類型更改為更長的類型(例如TEXT
),否則您無法將其轉換為utf8mb4
。同樣地,如果您想將非常長的
VARCHAR
欄位從utf8mb3
轉換為utf8mb4
,可能需要將其更改為較長的TEXT
類型之一。對於使用
COMPACT
或REDUNDANT
列格式的資料表,InnoDB
的最大索引長度為 767 個位元組,因此對於utf8mb3
或utf8mb4
欄位,您最多可以分別索引 255 或 191 個字元。如果您目前有索引長度超過 191 個字元的utf8mb3
欄位,則必須索引較少的字元。在使用
COMPACT
或REDUNDANT
列格式的InnoDB
資料表中,以下欄位和索引定義是合法的col1 VARCHAR(500) CHARACTER SET utf8mb3, INDEX (col1(255))
若要改用
utf8mb4
,索引必須更小col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))
注意對於使用
COMPRESSED
或DYNAMIC
列格式的InnoDB
資料表,允許使用長度超過 767 個位元組(最多 3072 個位元組)的索引鍵字首。使用這些列格式建立的資料表可讓您分別為utf8mb3
或utf8mb4
欄位索引最多 1024 或 768 個字元。如需相關資訊,請參閱第 17.21 節,「InnoDB 限制」和動態列格式。
只有在您有非常長的欄位或索引時,才最有可能需要上述類型的變更。否則,您應該可以使用先前描述的 ALTER TABLE
,將資料表從 utf8mb3
轉換為 utf8mb4
而不會出現問題。
以下項目總結了其他潛在的不相容性
SET NAMES 'utf8mb4'
會導致連線字元集使用 4 位元組字元集。只要伺服器沒有傳送 4 位元組的字元,就不應該有問題。否則,預期每個字元最多接收三個位元組的應用程式可能會出現問題。相反地,預期傳送 4 位元組字元的應用程式必須確保伺服器能夠理解它們。對於複製,如果要在來源上使用支援補充字元的字元集,則所有複本也必須能夠理解它們。
此外,請記住一般原則,如果資料表在來源和複本上的定義不同,可能會導致意料之外的結果。例如,最大索引鍵長度的差異使得在來源上使用
utf8mb3
,而在複本上使用utf8mb4
變得有風險。
如果您已轉換為 utf8mb4
、utf16
、utf16le
或 utf32
,然後決定轉換回 utf8mb3
或 ucs2
(例如,降級到較舊版本的 MySQL),則適用以下注意事項
utf8mb3
和ucs2
資料應該不會有問題。伺服器必須夠新才能識別參照您要轉換的字元集的定義。
對於參照
utf8mb4
字元集的物件定義,您可以使用 mysqldump 在降級之前傾印它們,編輯傾印檔案以將utf8mb4
的實例變更為utf8
,並在較舊的伺服器中重新載入檔案,前提是資料中沒有 4 位元組的字元。較舊的伺服器會在傾印檔案物件定義中看到utf8
,並建立使用 (3 位元組)utf8
字元集的新物件。