MySQL Charset--UTF8和UTF8MB4對比測試


UTF8和UTF8MB4

在早期MySQL版本中,使用只支持最長三字節的UTF8字符集便可以存放所有Unicode字符。隨着Unicode的完善,Unicode字符集收錄的字符數量越來越多,最新版本的UTF8需要使用1到4個字節來存放Unicode字符,而MySQL為保持版本兼容,依舊使用最多3字節的UTF8字符集,並在MySQL 5.5.3版本引入UTF8MB4字符集來支持4字節的Unicode字符。

漢字 '𤋮' 和 ' 𤋮 ' 是異體字,讀音均為xi,但兩個字的unicode不同:

𤋮 對應的UNICODE是 \ud850\udeee; 
𤋮 對應的UTF8是 ��
𤋮 對應的HEX編碼是 %f0%a4%8b%ae
熙 對應的UNICODE是 \u7199 
熙 對應的UTF8是
熙
熙 對應的HEX編碼是 %e7%86%99

 

在UTF8字符集模式下測試

創建測試表:

CREATE TABLE `tb5001` (
  `ID` INT(11) NOT NULL AUTO_INCREMENT,
  `C1` VARBINARY(100) DEFAULT NULL,
  `C2` VARCHAR(100) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=INNODB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4

在UTF8字符集下測試

SET NAMES utf8;

INSERT INTO TB5001(C1,C2)
SELECT '𤋮','𤋮';
INSERT INTO TB5001(C1,C2)
SELECT '','';

SELECT * FROM TB5001;

執行第一條INSERT有警告,警告信息為:

Warning Code : 1300
Invalid utf8 character string: 'F0A48B'

Warning Code : 1366
Incorrect string value: '\xF0\xA4\x8B\xAE' for column 'C2' at row 1

查詢結果為:

在UTF8字符集下,VARCHAR類型"無法支持“四字節的"𤋮",但VARBINARY不受字符集影響。

 

在UTF8MB4字符集模式下測試

測試腳本

SET NAMES utf8mb4;

INSERT INTO TB5001(C1,C2)
SELECT '𤋮','𤋮';

INSERT INTO TB5001(C1,C2)
SELECT '','';

SELECT * FROM TB5001;

測試中無任何警告,查詢結果:

在UTF8MB4字符集下,VARCHAR類型"完美支持“四字節的"𤋮",但VARBINARY不受字符集影響。

 

亂碼問題

表TB5001字符集已定義為UTF8MB4,表上C1列的字符集也是UTF8MB4,為啥還出現亂碼呢?

測試腳本:

SET NAMES utf8;
SELECT * FROM TB5001;

SET NAMES utf8mb4;
SELECT * FROM TB5001;

測試對比圖:

雖然表上C1列的字符集是UTF8MB4,能存放4字節的字符,但:

1、對於ID=33的記錄,由於在插入時使用UTF8字符集,在插入到C1列前'𤋮'字已經發生亂碼,存儲到C1列中數據也是亂碼,因此無論讀取時使用UTF8還是UTF8MB4都是亂碼。

2、對於ID-35的記錄,由於在插入時使用UTF8MB4字符集,插入C1列前和存儲到C1中都正常,在讀取時使用UTF8MB4能正常讀取,但在讀取使用UTF8是亂碼。

 

SET NAMES x相當於執行下面三條語句:

SET character_set_client = x;
SET character_set_results = x;
SET character_set_connection = x;

要保證數據庫正常存儲4字節的表情符合生僻字,除將數據庫相關表和列設置為UTF8MB4外,還需要確保操作數據庫時使用UTF8MB4,需重點關注以下幾個方面:

1、數據庫啟動配置參數

2、應用與數據庫連接配置

3、DBA日常運維操作

如DBA操作過程中,使用mysql客戶端連接到數據庫執行操作,而mysql客戶端可能使用默認UTF8字符集(default-character-set),導出亂碼問題。

 

在xshell工具下粘貼下面代碼:

SELECT '𤋮','𤋮';
SELECT '','';

將代碼粘貼到vim工具中自動變為:

SELECT '<d850><deee>','<d850><deee>';
SELECT '','';

將代碼粘貼到mysql命令總變為:

因此建議DBA在日常運維中關注生僻字和表情符,避免異常。

 

 

參考:http://seanlook.com/2016/10/23/mysql-utf8mb4/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM