MySQL 配置文件中忘配置default-character-set引起的亂碼問題

字符集參考文獻:html

http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_character_set_connectionmysql

http://dev.mysql.com/doc/refman/5.6/en/faqs-cjk.html
git

今天,一開發同事使用jdbc鏈接數據庫執行一條語句無結果集,可是經過sqlyou執行相同的語句有返回結果。github

執行的語句where條件中含有中文,這應該是字符集引發的sql

此開發測試實例剛遷移不久的,查看遷移前的環境默認字符集都是utf8數據庫

查看當前數據庫的字符集測試

mysql> show variables like '%charac%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | utf8                             |
| character_set_connection | utf8                             |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | utf8                             |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/mysql/share/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.00 sec)
  • character_set_client    
  • character_set_connection
  • character_set_results

   以上三個控制mysql client的字符集編碼

  • character_set_database  

          設置數據庫的默認字符集spa

  • character_set_server    

          設置以上全部的默認字符集code

發現server端的字符集和client端的全局字符集設置變量都是採用的默認值latin1

發現配置文件中沒有添加參數項  character-set-server=utf8

形成亂碼的緣由:

數據存儲時的編碼解碼過程

jdbc=>character_set_client=>table character

每一個環節的字符集編碼都是utf8,沒有轉碼過程

character_set_client變爲latin1後,讀取數據的解碼過程爲

jdbc<=character_set_client<=table character

表中存儲的是utf8編碼格式,判斷和character_set_client不一致則轉碼爲latin1的二進制流,而後傳輸給遠端的客戶端,

客戶端jdbc經過設置的字符集展現結果,使用utf8展現latin1,因此出現了亂碼。

解決辦法

# character_set_filesystem 、character_set_system 、character_sets_dir除外都變動全局爲utf8

全部的應用須要重連數據庫才能變動會話級別的字符集

對於在字符集設置爲latin1期間插入的數據編碼存儲過程:

  • 在terminal(這裏爲jdbc客戶端)中使用輸入法輸入
  • terminal轉換成utf8二進制流
  • 二進制流經過MySQL客戶端傳輸到MySQL Server
  • Server經過character-set-client解碼
  • 判斷character-set-client和目標表的charset是否一致,character-set-client爲latin1,目標表的字符集爲utf8
  • 不一致則進行一次從client-charset到table-charset的一次字符編碼轉換,由latin1轉碼爲utf8
  • 將轉換後的字符編碼二進制流存入文件中

測試這種狀況下將 中間環節的character-set-client變動爲utf8,是否會出現亂碼

mysql> show  variables like '%char%';      
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | latin1                           |
| character_set_connection | latin1                           |
| character_set_database   | utf8                             |
| character_set_filesystem | binary                           |
| character_set_results    | latin1                           |
| character_set_server     | utf8                             |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/mysql/share/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.01 sec)

mysql> update t1 set col='建軍節' where id=4;    

mysql> select * from t1 where id=4;
+----+-----------+------+
| id | col       | time |
+----+-----------+------+
|  4 | 建軍節    | NULL |
+----+-----------+------+


解碼編碼轉儲

crt terminal =》character_set_client =》character_set_server
		utf8          latin1                 utf8			
若是查詢時任何一個環節的字符集變化均可能會形成亂碼
更改不一樣環節的字符集對應的數據顯示
一、改變客戶端的字符集
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1 where id=4;
+----+-----------------------+------+
| id | col                   | time |
+----+-----------------------+------+
|  4 | ??o???è??             | NULL |
+----+-----------------------+------+
二、更改crt terminal 的字符集爲default
mysql> select * from t1 where id=4;
+----+-----------+------+
| id | col       | time |
+----+-----------+------+
|  4 | 寤哄啗鑺   | NULL |
+----+-----------+------+
三、更改表字段字符集
ALTER TABLE t1 CHANGE col col varchar(10) CHARACTER SET latin1;

mysql> select * from t1 where id=4;
+----+-----------+------+
| id | col       | time |
+----+-----------+------+
|  4 | 建軍節    | NULL |
+----+-----------+------+

 更改表的字符集爲latin1,讀取數據涉及到變動的環節變爲

  • 從文件讀出二進制數據流(utf8存入)
  • 用表字符集latin1編碼進行解碼
  • 將數據轉換爲character-set-client的編碼laint1

對應的變動前的環節:

  • 從文件讀出二進制數據流(utf8存入)
  • 用表字符集utf8編碼進行解碼
  • 將數據轉換爲character-set-client的編碼laint1

能夠看出更改表數據字符集沒有致使亂碼的緣由是,字符集總體經歷的解碼和轉碼過程是一致的,都經歷了一次由utf8到latin1的轉碼。

另外一有關字符集的問題:爲了支持表情符號,將系統級別的utf8設置爲utf8mb4且相應的表也作了字符集的轉變,重啓應用不生效,重啓數據庫和應用纔會生效

參考文章爲:

http://blog.sina.com.cn/s/blog_93b45b0f0101glfx.html

參考文章:

  編碼解碼過程  : http://cenalulu.github.io/mysql/mysql-mojibake/

相關文章
相關標籤/搜索