我們的一些業務系統最近出現了一種情況,尤其是新版的ios 設備,在發布消息時,使用了表情符號時,
對gbk 字符集的數據庫,寫入數據庫的數據,在回顯時,變成 ‘口口’ 無法回顯,
對utf8 字符集的數據庫,則根本無法寫入數據庫,客戶端程序直接報 java.io.exception xxxxxxxx.
原因在哪里呢?
各種移動設備,各種不同的輸入法,都會自帶一些增強版的'bmp' 表情符號。
這些表情符號編碼為 4個字節的 字符, utf8 字符集目前只支持1-3 個字節的字符,導致數據無法入庫。
解決方案 有兩種:
1. 遍歷輸入的文本,把四字節長度的字符,修正為自定義的字符替換掉,有一定的工作量。
2. 修改數據庫字符集, 把數據庫字符集從utf8 修改為支持1-4 個字節字符的utf8mb4
mysql 從 5.5.3 版本開始支持 utf8mb4 字符集 , 從 mysql 5.5.3 之后版本基本可以無縫升級到 utf8mb4 字符集。
3.升級方案:
1) 修改數據庫字符集character-set-server=utf8mb4 重啟數據庫生效。
[mysqld]
character-set-server=utf8mb4
2) 修改database 的字符集為 utf8mb4
alter database dbname character set=utf8mb4
3) 修改表的字符集 為utf8mb4
alter table tablename character set = utf8mb4
4. 需要注意的一些點。
1) innodb 索引只能支持 767 的字節,對utf8 大約可以為255 字符做索引, 對utf8mb4 就只有 191 個字符了,你的索引可能要重新定義。
2) 你的char varchar 的字段定義可能要重新定義或者修改為 text 類型。
3) utf8mb4 是utf8 的一個超集, utf8 字符的編碼,位置, 存儲 在utf8mb4 與utf8 字符集里一樣的,不會對有現有數據帶來損壞。
4) 謹慎起見,請詳細測試你的應用對該字符集的兼容性問題。
字符集設置:
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%'; +--------------------------+-----------------+ | Variable_name | Value | +--------------------------+-----------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | collation_connection | utf8_general_ci | | collation_database | utf8_general_ci | | collation_server | utf8_general_ci | +--------------------------+-----------------+ 10 rows in set (0.20 sec)
mysql> SET character_set_client = gbk; Query OK, 0 rows affected (0.31 sec) mysql> SET character_set_connection=gbk ; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_database=utf8mb4; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_filesystem=binary; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_results=gbk; Query OK, 0 rows affected (0.00 sec)
mysql> set character_set_system=utf8;
ERROR 1238 (HY000): Variable 'character_set_system' is a read only variable
mysql> set names gbk; 它相當於下面的三句指令: SET character_set_client = gbk; SET character_set_results = gbk; SET character_set_connection = gbk;
SET NAMES 'charset_name' COLLATE 'collation_name'
[client] //通過連接器連接 EG:PHP
[mysql] //mysql程序登陸時的字符集
default-character-set = gbk
//等價
--SET character_set_client = gbk;
--SET character_set_results = gbk;
--SET character_set_connection = gbk;
#character_set_system=utf8mb4 #character_set_client=utf8mb4 #character_set_connection=utf8mb4 #character_set_database=utf8mb4 #character_set_results=utf8mb4 // #代表相應變量不能設置在這個區中,報錯,mysql登陸報錯
[mysqld] //mysqld起動時設置字符集
character_set_filesystem=binary
character-set-server=utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='set autocommit=0; set names gbk;' //root 用戶不會執行
#character_set_system=utf8mb4
#character_set_client=utf8mb4
#character_set_connection=utf8mb4 //#代表相應變量不能設置在這個區中,mysqld 起動報錯
#character_set_database=utf8mb4
#character_set_results=utf8mb4
[]
[client] default-character-set = utf8 [mysqld] default-storage-engine = INNODB character-set-server = utf8 collation-server = utf8_general_ci
mysql> select * from t1; +------------+-----------------+---------------------+ | cur_user | n_user | in_time | +------------+-----------------+---------------------+ | @localhost | mysql@localhost | 2016-07-05 00:25:02 | +------------+-----------------+---------------------+ 1 row in set (0.19 sec) mysql> ALTER TABLE t1 MODIFY cur_user CHAR(50) CHARACTER SET sjis; mysql> show create table t1; CREATE TABLE `t1` ( `cur_user` char(50) CHARACTER SET sjis DEFAULT NULL, `n_user` varchar(100) CHARACTER SET utf8 DEFAULT NULL, `in_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
http://imysql.cn/2013/10/29/misunderstand-about-charset-handshake.shtml
character-set-client-handshake=1
Do not ignore character set information sent by the client. To ignore client information and use the default server character set,
use --skip-character-set-client-handshake; this makes MySQL behave like MySQL 4.0.
utf8mb4 字符集:
MySQL支持Emoji表情,涉及無線相關的 MySQL 數據庫建議都提前采用 utf8mb4 字符集。 utf8mb4和utf8到底有什么區別呢?原來以往的mysql的utf8一個字符最多3字節,而utf8mb4則擴展到一個字符最多能有4字節,所以能支持更多的字符集。 解決方案:將Mysql的編碼從utf8轉換成utf8mb4。 需要 >= MySQL 5.5.3版本、從庫也必須是5.5的了、低版本不支持這個字符集、復制報錯 停止MySQL Server服務 修改 my.cnf或者mysql.ini [client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-client-handshake = 0 character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect='SET NAMES utf8mb4' 重啟 MySQL Server、檢查字符集 mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%'; 修改數據庫字符集: ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; 修改表的字符集: ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 修改字段的字符集: ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 如果只是某個字段需要 只需要修改那個字段的字符集就可以了 另外服務器連接數據庫 Connector/J的連接參數中,不要加characterEncoding參數。 不加這個參數時,默認值就時autodetect。
