數據庫連接字符編碼問題


查看數據表字符編碼命令

show create table table_name;
show create table student;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                                                                                                                                                                              |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| student | CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(6) NOT NULL,
  `age` int(3) NOT NULL,
  `sex` varchar(2) DEFAULT NULL,
  `address` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

1 JDBC Driver使用的JDBC URL中關於字符編碼的配置參數主要有兩個:
useUnicode:是否使用自定義的編碼方案
characterEncoding:指定的編碼方案

一個具體的JDBC URL的例子如下:
jdbc:mysql://localhost:3306/demo1?useSSL=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull

這里的"characterEncoding"用來配置將字符流轉換成字節流的時候所使用的編碼方案,編碼得到的字節流將在網絡中傳輸。

整個轉換過程可以描繪成如下的步驟:
1)發送端使用配置的"characterEncoding"值,將字符流編碼成字節流
2)將1)中得到的字節流通過網絡傳輸到接收端
3)在接收端,已經預先接收獲取發送端配置的"characterEncoding"值,利用該值,解碼字節流,得到字符流

 

2 字符集和字符編碼

字符集(Character set)是多個字符的集合,字符集種類較多,每個字符集包含的字符個數不同,這里的字符可以是英文字符,漢字字符,或者其他國家語言字符。
常見字符集包括:ASCII字符集、LATIN1字符集、GB2312字符集、GBK字符集、GB18030字符集、Unicode字符集等。字符編碼方式是用一個或多個字節表示字符集中的一個字符。每種字符集都有自己特有的編碼方式,因此同一個字符,在不同字符集的編碼方式下,會產生不同的二進制。ASCII是基於羅馬字母表的一套字符集,它采用1個字節的低7位表示字符,高位始終為0。LATIN1字符集相對於ASCII字符集做了擴展,仍然使用一個字節表示字符,但啟用了高位,擴展了字符集的表示范圍。GB2312、GBK、GB18030字符集是支持中文的字符集,字符集范圍GB2312<GBK< GB18030。GBK字符集的字符有一字節編碼和兩字節編碼方式。對於00-7F的字符與ASCII保持一致,漢字采用2個字節表示。第一字節范圍是81-FE,避免與00-7F沖突。Unicode字符集是計算機科學領域里的一項業界標准,支持了所有國家的文字字符。Unicode字符集有好幾種編碼方式,比如常見的utf-8,utf-16,utf-32等。Utf8采用1-4個字節表示字符,utf-16采用固定的2個字節,utf-32則采用4個字節存儲。

 

3 msql 中字符集編碼環境變量

變量名

含義

character_set_server

默認的內部操作字符集

character_set_client

客戶端來源數據使用的字符集

character_set_connection

連接層字符集

character_set_results

查詢結果字符集

character_set_database

當前選中數據庫的默認字符集

character_set_system

系統元數據(字段名等)字符集 

詳細說明

3.1庫、表、列字符集的由來
(1).建庫時,若未明確指定字符集,則采用character_set_server指定的字符集。
(2).建表時,若未明確指定字符集,則采用當前庫所采用的字符集。
(3).新增,修改表字段時,若未明確指定字符集,則采用當前表所采用的字符集。

 

3.2 更新、查詢涉及到得字符集變量

用戶在更新(插入,刪除,修改),查詢數據庫時,最常使用的字符集變量主要包含character_set_client,character_set_connection,character_set_result。
更新流程字符集轉換過程:客戶端-》character_set_client-》character_set_connection-》表字符集。
查詢流程字符集轉換過程:表字符集-》character_set_result-》客戶端

 

3.3 mysql 字符編碼轉換過程

如果以上各個系統變量的設置不一致,比如character_set_client為UTF8,而character_set_database為GBK,則會出現需要進行編碼轉換的情況。那么字符集轉換的原理是什么?假設GBK字符集的字符串“小明”,需要轉為UTF8字符集存儲,實際就是對於“小明”字符串中的每個漢字去UTF8編碼表里面查詢對應的二進制,然后存儲,僅此而已,編碼轉換並不涉及到復雜的算法。mysql字符集轉換主要涉及到幾個步驟:

1) 將數據從character_set_client設置轉換為character_set_connection設置;

2) 將character_set_connection設置轉為表字段的字符集設置;

3) 將操作結果從表字段字符集轉為character_set_results設置。

下面我通過一個常用的場景來描述字符集轉換的流程。用戶通過mysql命令行(如果是遠程連接:SecureCRT),敲入命令“insert into T values(1,’小明’)”,字符串’小明’在流轉過程中二進制存儲內容。

a) 用戶采用的客戶端為utf8字符集,character_set_client=gbk,character_set_connection=gbk, 表T采用gbk字符集。

 

由於character_set_client、character_set_connection和表字符集均為GBK,不涉及編碼轉換。因此,表雖然為字符集雖然為GBK,但“小明”的編碼並非為GBK編碼的二進制流,而是UTF8的二進制流,兩個漢字占用了6個字節,而讀取則是一個逆向的過程,不涉及到編碼轉換,查詢依然能正確返回“小明”。

b)  在a)的情況下,改變character_set_client的設置為utf8,查詢插入的值。

 

可以看到返回的值是“灝忔槑”, 這是由於表的字符集是GBK,而客戶端請求是UTF8,那么server將二進制流E5B08FE6988E對應的GBK漢字“灝忔槑”轉為UTF8漢字對應的二進制流E7818FE5BF94E6A791,因此查詢結果在SecureCRT就顯示為“灝忔槑”,即通常我們所謂的亂碼。

c) 在b)的情況下,設置SecureCRT的字符集為GBK,看看SecureCRT字符集設置對結果影響

 

可以看到返回的是另外一組字符“鐏忓繑妲�”,整個流轉過程與b)一樣,只是在第一步發生了字節流轉換,設置SecureCRT字符集編碼,只是改變了顯示方式。

 

4 查看當前數據庫配置文件位置

4.1 在linux系統中可以通過使用命令查詢

# which mysqld
/usr/local/mysql/bin/mysqld
# /usr/local/mysql/bin/mysqld --verbose --help |grep -A 1 'Default options'
2016-06-02 16:49:39 0 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.6.25-log) starting as process 8253 ...
2016-06-02 16:49:41 8253 [Note] Plugin 'FEDERATED' is disabled.
Default options are read from the following files in the given order: 默認的選項是按照給定的順序讀取從以下文件:
/etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf 

 

4.2 在 window 系統查看可以使用mysql workbench點擊server status即可

 


免責聲明!

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



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