深入瞭解mysql數據傳輸編碼原理

来源:http://www.cnblogs.com/jave1ove/archive/2017/08/30/7454966.html
-Advertisement-
Play Games

一、基本概念(這裡引用http://www.laruence.com/2008/01/05/12.html) 1、 給定一系列字元,對每個字元賦予一個數值,用數值來代表對應的字元,這一數值就是字元的編碼(Encoding)。例如,我們給字元’A'賦予數值0,給字元’B'賦予數值1,則0就是字元’A' ...


一、基本概念(這裡引用http://www.laruence.com/2008/01/05/12.html

1、 給定一系列字元,對每個字元賦予一個數值,用數值來代表對應的字元,這一數值就是字元的編碼(Encoding)。例如,我們給字元’A'賦予數值0,給字元’B'賦予數值1,則0就是字元’A'的編碼;

2、 給定一系列字元並賦予對應的編碼後,所有這些字元和編碼對組成的集合就是字元集(Character Set)。例如,給定字元列表為{‘A’,'B’}時,{‘A’=>0, ‘B’=>1}就是一個字元集;

3、字元序(Collation)是指在同一字元集內字元之間的比較規則;

4、確定字元序後,才能在一個字元集上定義什麼是等價的字元,以及字元之間的大小關係;

5、每個字元序唯一對應一種字元集,但一個字元集可以對應多種字元序,其中有一個是預設字元序(Default Collation);

6、MySQL中的字元序名稱遵從命名慣例:以字元序對應的字元集名稱開頭;以_ci(表示大小寫不敏感)、_cs(表示大小寫敏感)或_bin(表示按編碼值比較)結尾。例如:在字元序“utf8_general_ci”下,字元“a”和“A”是等價的;

二、名詞解釋

1、character_set_client:客戶端數據解析、編碼的字元集。

2、character_set_connection:連接層字元集。

3、character_set_server:伺服器內部操作字元集。

4、character_set_results:查詢結果字元集。

5、character_set_database:當前資料庫的字元集。

6、character_set_system:系統源數據(欄位名等)字元集。

註:

1、還有以collation_開頭的同上面對應的變數,用來描述字元序。

2、服務端編碼、解析時,是按照前一環節的編碼進行解析的,按照各自的字元集進行編碼的。

3、character_set_server是mysql資料庫記憶體的操作字元集。如果創建資料庫時,沒有指定資料庫的字元集,則使用character_set_server的字元集作為預設字元集;如果創建表時,沒有指定表的字元集,則使用character_set_database的字元集作為預設字元集;如果在創建欄位時,沒有指定欄位的字元集,則使用表的字元集作為預設字元集。

4、set names gbk;等同於同時設置character_set_client,character_set_connection,character_set_results這三個字元集。

三、數據傳輸過程中字元集編碼、解析

1.客戶端以及編碼

        我們使用jdbc操作數據的程式、navicate操作工具、操作系統操作資料庫這些都認為是客戶端。客戶端navicate的編碼為utf8,windows預設的編碼為gbk。一般情況下,utf8編碼的中文占三個位元組,gbk占用兩個位元組(一個位元組是8位二進位,也就是兩個十六進位)。

Navicate操作(utf8)

mysql> show variables like '%char%';

+--------------------------+----------------------------+

| 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                       |

| character_sets_dir       | /usr/share/mysql/charsets/ |

+--------------------------+----------------------------+

8 rows in set

 

mysql> select hex('我很帥');

+--------------------+

| hex('我很帥')      |

+--------------------+

| E68891E5BE88E5B885 |

+--------------------+

1 row in set
Windows上操作(gbk)

mysql> show variables like '%char%';

+--------------------------+----------------------------+

| Variable_name            | Value                      |

+--------------------------+----------------------------+

| character_set_client     | gbk                        |

| character_set_connection | gbk                        |

| character_set_database   | utf8                       |

| character_set_filesystem | binary                     |

| character_set_results    | gbk                        |

| character_set_server     | utf8                       |

| character_set_system     | utf8                       |

| character_sets_dir       | /usr/share/mysql/charsets/ |

+--------------------------+----------------------------+

8 rows in set

 

mysql> select hex('我很帥');

+--------------------+

| hex('我很帥')      |

+--------------------+

| CED2BADCCAA7       |

+--------------------+

1 row in set

2.解析過程

a.sql語句通過客戶端編碼發送到mysql伺服器上;

b.character_set_client對接收到的數據進行解碼,這裡解碼按照character_set_client編碼進行解碼,最後按照自身字元集進行編碼。

c.character_set_connection收到來自client的編碼,這裡進行字元集轉換。註意這裡s.decode(character_set_client).encode(character_set_connection)。

d.character_set_server這裡是伺服器內部使用的字元集,如果單獨給欄位添加字元集,這裡取的是欄位字元集。這裡收到connection的編碼,進行字元集轉換。e.decode(character_set_connection).encode(character_set_server)。

3.查詢過程

a.mysql伺服器轉換為character_set_results發送到客戶端,其實這裡你只要知道最後從伺服器出來的時候是按照character_set_results編碼的。

b.發送到客戶端之後,按照客戶端編碼進行解碼。所以如果character_set_results和客戶端編碼不一致,會導致查詢亂碼。

ps:這裡我創建一個gbk表,裡面插入有數據(自己構造,帶有中文)。

Navicate操作(utf8)

mysql> select @@character_set_results;

+-------------------------+

| @@character_set_results |

+-------------------------+

| utf8                    |

+-------------------------+

1 row in set

 

mysql> select name_man from wsyy_marry where id = 1;

+----------+

| name_man |

+----------+

| 赫立廣   |

+----------+

1 row in set

 

mysql> set @@session.character_set_results = 28;

Query OK, 0 rows affected

 

mysql> select @@character_set_results;

+-------------------------+

| @@character_set_results |

+-------------------------+

| gbk                     |

+-------------------------+

1 row in set

 

mysql> select name_man from wsyy_marry where id = 1;

+----------+

| name_man |

+----------+

| ������   |

+----------+

1 row in set
Windows操作(gbk)

mysql> select @@character_set_results;

+-------------------------+

| @@character_set_results |

+-------------------------+

| gbk                     |

+-------------------------+

1 row in set

 

mysql> select name_man from wsyy_marry where id = 1;

+----------+

| name_man |

+----------+

| 赫立廣   |

+----------+

1 row in set

 

mysql> set @@session.character_set_results = 33;

Query OK, 0 rows affected

 

mysql> select @@character_set_results;

+-------------------------+

| @@character_set_results |

+-------------------------+

| utf8                    |

+-------------------------+

1 row in set

 

mysql> select name_man from test.wsyy_marry where id = 1;

+----------+

| name_man |

+----------+

| 璧珛騫�   |

+----------+

1 row in set

四、總結

1、字元集設置33,代表utf8;28代表gbk字元集設置33;

2、字元集出現亂碼的地方最大可能在兩個地方,character_set_client和character_set_results。如果這兩個地方的編碼個客戶端編碼不一致會亂碼。告訴你,有可能存都存不進去。

3、後面也有可能出現編碼問題,如果中文字元串,latin1解碼不了中文,則會出現亂碼。也就是說進行編碼轉換的時候可能出現不相容的情況,latin1編碼的都能被utf8相容,反之就可能出現”??”這樣的情況。

4、看下來之後老老實實不要亂設置character_set_client這些值。如果能保持所有的都是utf8,那肯定沒問題。

五、疑問

客戶端編碼

client

connection

server

結果

utf8

gbk

gbk

gbk/utf8

插入失敗

utf8

gbk

utf8

gbk/utf8

插入亂碼

utf8

utf8

gbk

gbk/utf8

正常插入

utf8

urf8

utf8

gbk/utf8

正常插入

 

 

 

 

 

 

 

 

我做瞭如下統計,客戶端編碼和character_set_client編碼不一致有可能出現插入亂碼,也有可能出現數據插都插不進去。我也不知道為啥會不能插入資料庫。下麵這兩種情況很大都是可能是亂碼導致的報錯。

1、Incorrect string value: '\xB6' for column 'NAME_MAN' at row 1。

2、SQLException errorcom.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'NAME_MAN' at row 1。

如果對這裡面介紹有異議或者能有更全面的理解可以在下麵留言,大家共同學習。

六、參考資料

1.http://www.jianshu.com/p/96ee5b2adef3

2.http://blog.csdn.net/kxcfzyk/article/details/37723367

3.http://www.laruence.com/2008/01/05/12.html

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 資源使用 Android 中支持三種格式的點陣圖文件:.png(首選), .jpg(可接受),.gif(不建議) 為什麼首推 PNG 呢? 官網的描述如下: 註:在構建過程中,可通過 aapt 工具自動優化點陣圖文件,對圖像進行無損壓縮。例如,不需要超過 256 色的真彩色 PNG 可通過調色板轉換為 ...
  • 在開始之前,我們需要創建一個DrawRectView 其初始代碼為 在ViewController中使用(尺寸為100x100並居中) 顯示效果如下(用紅色邊框顯示邊界) 修改DrawRectView.m代碼如下 其實就添加了下麵的繪圖代碼而已,繪製7條線條,每條線條的寬度為0.5 效果如下 將圖片 ...
  • 官方鏈接: https://developer.apple.com/app-store/review/guidelines/cn/ 1.條款和條件 1.1為App Store開發程式,開發者必須遵守Program License Agreement (PLA)、人機交互指南(HIG)以及開發者和蘋果 ...
  • 手機歸屬地查詢 效果圖: 分析: 1、傳遞多個參數,用一個類就好 2、打開資料庫 private SQLiteDatabase database; database=SQLiteDatabase.openOrCreateDatabase(file, null); file是資料庫的路徑 3、在邏輯中 ...
  • 首先,需要添加com.android.support:percent:24.1.1 包,版本隨意。 } 這個包給我們提供了PercentRelativeLayout以及PercentFrameLayout兩種佈局, 支持的屬性有layout_widthPercent、layout_heightPer ...
  • eclipse中打字中文突然變成繁體 在用eclipse做android項目的時候,發現打出來的字全部是繁體,而且QQ等其他位置又是簡體。 原因:eclipse的快捷點ctrl+alt+f(format代碼) 和搜狗裡面的切換簡繁體的快捷鍵一樣了。 所以也會導致在eclipse中ctrl+alt+f ...
  • 1. MNIST數據集 1.1 概述 Tensorflow框架載tensorflow.contrib.learn.python.learn.datasets包中提供多個機器學習的數據集。本節介紹的是MNIST數據集,其功能都定義在mnist.py模塊中。 MNIST是一個入門級的電腦視覺數據集,它 ...
  • select u.c_name,case when ur.c_role_id=73 then 'A類型' else 'B類型' end as roletype, case when u.c_online_status=1 then'線上' else '不線上' end as onlinestatus... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...