1、MySQL字符集編碼簡單介紹
在使用MySQL時要注意6個須要編碼的地方:系統的編碼、客戶端、服務端、庫、表、列。字符集編碼不只影響數據存儲,還影響client程序和數據庫之間的交互.在mysql中輸入命令show session variables like '%char%'可以看到例如如下一些字符集(下面是以win10爲例,生產中多數時linux,在linux裏面除了latin1以外都是utf8的字符集):mysql
mysql> show variables like "%char%";
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | gbk |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | F:\jj\mysql-5.6.42-winx64\share\charsets |
+--------------------------+-------------------------------------------+linux
8 rows in set (0.00 sec)sql
mysql中的字符集都相應着一個默認的校對規則(COLLATION),固然一個字符集也可能相應多個校對規則,但是兩個不一樣的字符集不能相應同一個規則。使用默認的就能夠了數據庫
如下來看看上面命令列出的字符集相關變量的含義:服務器
- character_set_client:server解析客戶端sql語句的字符集.(The character set for statements that arrive from the client. The session value of this variable is set using the character set requested by the client when the client connects to the server).
- character_set_connection:字符串字面值(literal strings)的字符集.
- character_set_results:server返回給客戶端的查詢結果或者錯誤提示的字符集編碼.(The character set used for returning query results such as result sets or error messages to the client)
- character_set_system:這是mysqlserver用來存儲元數據的編碼,一般就是utf8,不要去改動它.
- character_sets_dir:這是mysql字符集編碼存儲文件夾.
- character_set_filesystem:這是文件系統字符集編碼,主要用於解析用於文件名稱的字符串字面值,如LOAD DATA INFILE和SELECT ...INTO OUTFILE等語句以及LOAD_FILE()函數.在打開文件以前,文件名稱會從character_set_client轉換爲character_set_filesystem指定的編碼.默認值爲binary,也就是說不會進行轉換.好比咱們設置的character_set_client=GBK,而character_set_filesystem爲默認值的話,則採用SELECT...INTO OUTFILE "文件名稱",文件名稱爲GBK編碼.反之,假設咱們設置了character_set_filesystem=UTF8,則導出的文件名稱爲UTF8編碼. 好比:linux系統的終端編碼是UTF8,系統默認語言和編碼爲zh_CN.UTF8.咱們有一個數據庫名爲test,test中有個表名爲t1,編碼爲latin1,另外,咱們在mysqlclient運行了SET NAMES GBK,假設咱們不改動character_set_filesystem的值,運行SELECT * FROM t1 INTO OUTFILE '文件1', 可以發現相應的文件夾如下生成了一個名爲"文件1"的文件,那文件名稱編碼是什麼呢?事實上這裏有幾個地方需要注意,首先,咱們的sql語句裏面的"文件1"原生編碼就是終端編碼UTF8,也就是'\xe6\x96\x87\xe4\xbb\xb61',而導出數據的語句SELECT * FROM t1 INTO OUTFILE '文件1',依照前面的說法,因爲character_set_filesystem爲binary,所以'\xe6\x96\x87\xe4\xbb\xb61'不會轉換,這樣終於仍是'\xe6\x96\x87\xe4\xbb\xb61',這樣在zh_CN.UTF8的系統中文件名稱不會亂碼.而假設咱們設置了character_set_filesystem=UTF8,則原生的'\xe6\x96\x87\xe4\xbb\xb61'會先依照GBK解碼,而後用UTF8編碼,最後的結果是"\xe9\x8f\x82\xe5\x9b\xa6\xe6\xac\xa21",這樣文件名稱就會亂碼了.因此這個變量也最好不要改動,用默認值就OK.
- character_set_server:服務器默認字符集編碼,假設建立數據庫的時候沒有指定編碼,則採用character_set_server指定編碼.
- character_set_database:默認數據庫的字符集編碼.假設沒有默認數據庫,則該變量值與character_set_server一樣.事實上這個值表明的就是你當前數據庫的編碼而已,比方使用"use test",而test數據庫的編碼爲latin1的話,這個值就是latin1.而你切換的時候"use test2",則character_set_database的值就是數據庫test2的編碼.
2、MySQL字符集編碼層次
第一部分主要是概括了MySQL文檔中關於字符集編碼的說明。這部分主要說明下MySQL中字符集編碼層次:服務端-->數據庫-->表-->字段。session
關於系統的編碼主要針對的是咱們未來在存儲文件的時候,有可能會將文件直接存貯在mysql的服務器上,那麼,咱們在數據庫裏面存的就是這些文件的路徑,實際文件是存在系統裏面的,那麼文件名稱就會受到你係統編碼的影響,好比咱們mysql設置的utf8編碼的格式存儲的文件路徑,可是系統默認是gbk編碼的,那麼文件在保存到系統裏的時候,文件的名稱和你存在mysql裏面的文件名稱就對應不上了,出現亂碼顯示的問題,因此也要注意系統的編碼。客戶端的編碼問題,咱們在第一節的時候說了一下,你們應該比較瞭解啦。因此咱們下面之說mysql內部設置的這些編碼問題。函數
簡單來講,服務器編碼就是character_set_server來指定的.當咱們建立數據庫的時候可以指定編碼,假設沒有指定,採用的就是character_set_server指定的編碼.好比:咱們使用"create database t1 character set gbk",這裏咱們指定了數據庫t1的編碼爲gbk,因此不會採用character_set_server指定的編碼.而假設咱們使用"create database t2",則經過"show create database t2"可以看到t2的編碼爲character_set_server定的編碼.sqlserver
同理,mysql表也可以有本身獨立的編碼,在建立表的時候可以指定,假設沒有指定,則默認採用數據庫的編碼.比方咱們再以前的數據庫t1建立表t11,"create table t11(i int) character set utf8",則表t11的編碼爲utf8,假設不指定編碼則編碼爲數據庫t1的編碼gbk.this
此外,mysql表中的字段也可以有本身的編碼,假設不指定字段編碼,則字段編碼與表的編碼一致.編碼
3、MySQL鏈接字符集
前面談到的編碼內容基本都不會產生亂碼問題,mysql中容易產生亂碼的地方在character_set_client, character_set_connection, character_set_results這三個變量的設定.可以簡單的經過set names utf8或者charset utf8命令來一次設置這三個參數.
從文檔中的解釋來看,mysql鏈接字符集轉換主要包含如下三個步驟:
- 1.character_set_client是client發送過來的sql語句的編碼,因爲服務端自己並不知道client的sql語句的編碼是什麼,因此是以這個變量做爲clientsql語句的初始編碼.而服務端接收到sql語句後,則會將sql語句轉換爲character_set_connection指定的編碼(注意,對於字面值字符串,假設前面有introducer標記如latin1或utf8,則不會進行這一步轉換).轉換完畢,纔會真正運行sql語句.
- 2.進行內部操做前將sql語句中的數據從character_set_connection轉換爲數據表中對應字段的編碼.
- 3.將操做結果從內部字符集編碼轉換爲character_set_results編碼.