【勝通】mysql連線通道中的字符集和校驗規則
這裡首先需要解釋的是,我想應該就是連線通道的含義了。那什麼是連線通道呢?
所謂連線通道,就是客戶端和伺服器端保持連線的一個通道,它是邏輯上的一個概念。客戶端通過連線通道傳送sql語句到伺服器端,服務端執行,將結果再通過連線通道返回至客戶端。the connection is the pass when you connect to the server.
這個過程中,有幾個臨界點(邏輯上概念),是我們需要注意的,mysql也就在這幾個臨界點上做了文章。
1、當語句離開客戶端的時候:
從客戶端出來的,包括sql語句本身(這裡裡面就包含字串和關鍵字等了),以及character_set_client系統變數。為什麼要包含這個變數呢?這個變數的作用說明2點,也是它的作用:一是表示該語句中的字符集是使用character_set_client指定的字符集編碼的,二是通過此係統變數來告訴伺服器所傳送來的語句中的字符集編碼。
2、當伺服器端接受到客戶端的語句的時候:
mysql會使用character_set_connection/collation_connection指定的字符集以及校驗規則,將客戶端的字串,做一個從character_set_client到character_set_connection的轉換。
3、當伺服器處理好結果以後,在把結果傳給客戶端前:
mysql會先將結果轉換成character_set_results指定的字符集,然後傳回給客戶端。
當字串在mysql伺服器的時候,最終以什麼格式儲存到mysql資料庫中,這個是受到具體的資料表級別、列級別字符集設定的控制了。
從上面的介紹中,我們就知道和連線通道相關幾個引數了,他們分別是character_set_client/connection/results,可以如下檢視:
+--------------------------+-------------------+
| Variable_name | Value |
+--------------------------+-------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | gbk |
| character_set_results | latin1 |
| .........................| ...... |
+--------------------------+-------------------+
8 rows in set (0.00 sec)
mysql> show variables like 'colla%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | gbk_bin |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
下面我們來做個實驗,來證明一下這個結果:
首先保證character_set_connection與character_set_results以及底層儲存字符集的一致性,看看character_set_client的效果。
+--------------------------+------------------+
| Variable_name | Value |
+--------------------------+------------------+
| character_set_client | latin1 |
| character_set_connection | gbk |
| character_set_database | gbk |
| character_set_results | gbk |
| .........................| ...... |
+--------------------------+------------------+
8 rows in set (0.00 sec)
mysql> create table t (a varchar(10)); -- 這裡沒有指定字符集,就預設使用了database的字符集gbk了
Query OK, 0 rows affected (0.08 sec)
mysql> insert into t values('中國');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+-------+
| a |
+-------+
| ???ú |
+-------+
1 row in set (0.00 sec)
由此可以看到由於latin1與gbk對漢字的編碼方式不一樣(或者說latin1根本就不能正確編碼漢字),在這個collection過程中,從character_set_client到character_set_connection轉換時,就把你輸入的好好的漢字轉換成亂碼了。那麼,如果讓過程不發生轉換呢?
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t values('人民');
Query OK, 1 row affected (0.02 sec)
mysql> select * from t;
+-------+
| a |
+-------+
| ???ú |
| 人民 |
+-------+
2 rows in set (0.00 sec)
可見,這裡是能正確儲存和顯示的,很簡單,因為任何轉換都沒有發生,當然就不會出現亂碼了。
接著做實驗,我們讓character_set_connection發生變化:
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t values ('共和國');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+-------+
| a |
+-------+
| ???ú |
| 人民 |
| ??? |
+-------+
3 rows in set (0.00 sec)
可見,這裡character_set_client=gbk,character_set_connection=latin1,character_set_database=gbk。首先,client到connection過程中,漢字被轉換成亂碼(這個過程可能就會丟失資訊);然後儲存資料的時候,又從connection到儲存的字符集(gbk)發生一次轉換,亂碼被轉換成“更”亂碼。這裡如果connection與client的字符集有種包容性關係的話,如character_set_client=gbk, character_set_connection=utf8,character_set_results=gbk,底層儲存也是gbk編碼,由於utf8“相容”所有的字符集,故在轉換過程中不會發生資訊丟失,查詢的時候也不會是亂碼,如下:
+--------------------------+-----------------+
| Variable_name | Value |
+--------------------------+-----------------+
| character_set_client | gbk |
| character_set_connection | utf8 |
| character_set_database | gbk |
| character_set_results | gbk |
| .........................| ...... |
+--------------------------+-----------------+
8 rows in set (0.00 sec)
mysql> create table t (a varchar(10)) charset=gbk;
Query OK, 0 rows affected (0.05 sec)
mysql> insert into t values('中國');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+------+
| a |
+------+
| 中國 |
+------+
1 rows in set (0.00 sec)
我來解釋一下這個過程,假設“中國”的gbk編碼是1234,而utf8的編碼是4321,utf8的編碼為1234的假設是“淘寶”。client的“中國”的編碼1234進入connection,仍然是1234(但實際上它的含義已經發生變化為“淘寶”),儲存的時候connection的1234編碼到表儲存也是1234,剛好正確表達了“中國”的意思,查詢返回時,由於results也是gbk,所以不發生轉換,正確顯示。很顯然,如果results又是一種與gbk不相容的字符集如latin1,查詢又會出問題,如下:
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t;
+------+
| a |
+------+
| ?? |
+------+
1 rows in set (0.00 sec)
當我們改變底層儲存的字符集的時候,會怎樣?請看如下實驗:
+--------------------------+---------------+
| Variable_name | Value |
+--------------------------+---------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_database | gbk |
| character_set_results | gbk |
| .........................| ...... |
+--------------------------+---------------+
8 rows in set (0.01 sec)
mysql> create table t (a varchar(10)) charset=latin1;
Query OK, 0 rows affected (0.05 sec)
mysql> insert into t values('淘寶');
Query OK, 1 row affected, 1 warning (0.02 sec)
mysql> select * from t;
+------+
| a |
+------+
| ?? |
+------+
1 row in set (0.00 sec)
很顯然,由於latin1字符集無法儲存漢字,故出現亂碼。
下面,我們只改變results字符集,看看效果如何:
+--------------------------+----------------+
| Variable_name | Value |
+--------------------------+----------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_database | gbk |
| character_set_results | latin1 |
| .........................| ...... |
+--------------------------+----------------+
8 rows in set (0.00 sec)
mysql> create table t (a varchar(10)) charset=gbk;
Query OK, 0 rows affected (0.08 sec)
mysql> insert into t values('淘寶');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+------+
| a |
+------+
| ?? |
+------+
1 row in set (0.00 sec)
很顯然,底層為gbk編碼的字串轉換成latin1的字符集的字元,變成亂碼,傳給客戶端,再次轉換成gbk字符集,變成“更”亂碼,故顯示亂碼。
下面,我再介紹幾個“簡約”命令。
SET NAMES ‘x’,(SET NAMES ‘charset_name’ COLLATE ‘collation_name’)相當於:
SET character_set_client = x;
SET character_set_results = x;
SET character_set_connection = x;
實驗如下:
+--------------------------+----------------+
| Variable_name | Value |
+--------------------------+----------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_results | latin1 |
| .........................| ...... |
+--------------------------+----------------+
8 rows in set (0.00 sec)
mysql> set names 'ascii';
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'char%';
+--------------------------+----------------+
| Variable_name | Value |
+--------------------------+----------------+
| character_set_client | ascii |
| character_set_connection | ascii |
| character_set_results | ascii |
| .........................| ...... |
+--------------------------+----------------+
SET CHARACTER SET ‘x’,相當於:
SET character_set_client = x;
SET character_set_results = x;
SET collation_connection = @@collation_database;
這裡collation_connection = @@collation_database的意思就是把collation_connection的設定的collation_database的值,由於collation肯定能確定character set,故其又相當於多做了個設定:把character_set_connetion設定成character_set_database的值。請看如下實驗:
+--------------------------+-------------+
| Variable_name | Value |
+--------------------------+-------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | gbk |
| character_set_results | latin1 |
| ....................... | ...... |
+--------------------------+-------------+
8 rows in set (0.00 sec)
mysql> show variables like 'collat%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | gbk_bin |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
mysql> set character set 'ascii';
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'char%';
+--------------------------+-------------+
| Variable_name | Value |
+--------------------------+-------------+
| character_set_client | ascii |
| character_set_connection | gbk |
| character_set_database | gbk |
| character_set_results | ascii |
| ....................... | ...... |
+--------------------------+-------------+
8 rows in set (0.00 sec)
mysql> show variables like 'collat%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | gbk_bin |
| collation_database | gbk_bin |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
通過以上的介紹,所以為了防止出現亂碼,我們可以把character_set_client,character_set_connection,character_set_database,character_set_results設定成同樣的值,把collation_connection和collation_database也設定成同樣的值,這樣就“一勞永逸”了。程式連線mysql的時候,一般都會顯示設定character_set_client的值,如java連線中,一般都有如下的一段程式碼來顯示設定這個值:
<!--jdbc:mysql://10.1.6.174:3306/notify?connectTimeout=1000&characterEncoding=utf8
http://rdc.taobao.com/blog/dba/html/184_mysql_connect_charset_collation.html/trackback
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1384/viewspace-374818/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【勝通 】mysql字符集與校驗規則的設定MySql
- MySQL字符集和校對規則(Collation)MySql
- mysql的字符集校對規則MySql
- MySQL字符集和校對規則(character set & collation)MySql
- Vue中form表單常用rules校驗規則VueORM
- 校驗檔案的搜尋規則
- 從根上理解 MySQL 的字符集和比較規則MySql
- springMVC:校驗框架:多規則校驗,巢狀校驗,分組校驗;ssm整合技術SpringMVC框架巢狀SSM
- 如何本機通過 SSH 通道連線雲伺服器 MySQL伺服器MySql
- 前端Vue中常用rules校驗規則前端Vue
- 【MySQL】資料庫字元校對規則MySql資料庫字元
- MySQL中的排序規則MySql排序
- 如何利用SSH通道來連線遠端的MysqlMySql
- element-ui自定義表單校驗規則及常用表單校驗UI
- 塗抹MySQL--第6章 開源運動與開源軟體MySQL - 6.1字符集和校對規則MySql
- SpringBoot專案校驗規則優化Spring Boot優化
- sentinel流控規則校驗之原始碼分析原始碼
- 關於mysql字符集及排序規則設定MySql排序
- mysql 通過IP連線MySql
- Mysql的下載,安裝,遠端連線,密碼加密規則修改。MySql密碼加密
- 通過跳板機連線MySQLMySql
- 常用後端正則校驗後端
- mysql5.1官方文件連線_字符集詳解MySql
- SQLServer的排序規則(字符集編碼)SQLServer排序
- [提問交流]模型管理中的欄位【驗證規則】和【自動完成規則】怎麼用?模型
- 【勝通 】mysql的引數變數MySql變數
- SQL中的左連線和右連線SQL
- Vue Element-ui表單校驗規則,你掌握了哪些?VueUI
- 通過驅動建立與MySQL的連線MySql
- 對線面試官:Mysql組合索引的生效規則面試MySql索引
- node+express框架中連線使用mysql經驗總結Express框架MySql
- DDD中實現業務規則的驗證 - Marcin
- laravel 校驗規則 Rule::in 等對中文字元不友好的問題Laravel字元
- MySQL 的啟動和連線方式MySql
- MySQL和Oracle中的半連線測試總結(一)MySqlOracle
- Laravel的unique和exists驗證規則的優化Laravel優化
- (6)mysql 中的字符集MySql
- 前端 - 開發中常用的正則校驗前端