深入了解mysql数据传输编码原理
一、基本概念(这里引用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
深入了解mysql数据传输编码原理的更多相关文章
- MYSQL索引结构原理、性能分析与优化
[转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...
- MySQL字符集编码
MySQL字符集编码总结 之前内部博客上凯哥分享了一篇关于mysql字符集的文章,之前我对mysql字符集一块基本没有深究过,看到凯哥文章后有些地方有点疑惑,遂自己去看了mysql的官方文档,并參考了 ...
- MYSQL转换编码的解决方法
MYSQL转换编码的解决方法 一.在utf8的mysql下 得到中文‘游客’的gbk下的16进制编码 mysql> SELECT hex(CONVERT( '游客' USING gbk )); ...
- 你的MySQL服务器开启SSL了吗?SSL在https和MySQL中的原理思考
最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主 ...
- MySQL 储存过程-原理、语法、函数详细说明
Mysql储存过程是一组为了完成特定功能的SQL语句集,经过编译之后存储在数据库中,当需要使用该组SQL语句时用户只需要通过指定储存过程的名字并给定参数就可以调用执行它了,简而言之就是一组已经写好的命 ...
- 【转】由浅入深探究mysql索引结构原理、性能分析与优化
摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1.简单介绍B-tree B+ tree树 2.MyisAM索引结构 3.Annode索引结构 4.MyisAM索引与Inno ...
- H264编码原理以及I帧、B和P帧详解, H264码流结构分析
H264码流结构分析 http://blog.csdn.net/chenchong_219/article/details/37990541 1.码流总体结构: h264的功能分为两层,视频编码层(V ...
- xss的编码原理
把以前的笔记翻出来整理一下 最前方 xss如何选用编码原理,为什么 找到的挺清楚的文章了:https://www.cnblogs.com/p0laris/p/11898322.html浏览器解析有两种 ...
- mysql utf8编码
做微信项目,报错 "Incorrect string value: '\\xF0\\x9F\\x98\\x8B' for column 'nickname' at row 1" 原 ...
随机推荐
- 华为OJ之最长公共子串
题目描述: 对于两个给定的字符串,给出他们的最长公共子串. 题目分析: 1,最长公共子串(LCS)实际上是最长公共子序列的一种特殊情况,相当于是求连续的最长子序列.我们今天先解决这个特殊情况,后续博文 ...
- C#监控类属性的更改(大花猫动了哪些小玩具)
C#监控类属性的更改(大花猫动了哪些小玩具) 实体类创建后在方法中对哪些属性赋值了,传递到底层方法时在底层如何得知哪些属性被赋值过.如何监控属性的更改,请看脑洞大开之<大花猫动了哪些小玩具> ...
- 机器学习 —— 基础整理(三)生成式模型的非参数方法: Parzen窗估计、k近邻估计;k近邻分类器
本文简述了以下内容: (一)生成式模型的非参数方法 (二)Parzen窗估计 (三)k近邻估计 (四)k近邻分类器(k-nearest neighbor,kNN) (一)非参数方法(Non-param ...
- Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口
Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...
- [IB]PeopleSoft异步详细信息中状态“已完成”但订阅合同状态“新建”问题
最近遇到一个IB异步程序状态不一致问题,异步详细信息中上面的状态是“DONE”但是订阅合同中还是“新建”状态.在域状态中清除域状态也不管用. 重启app server也不好使.最后执行了appmsgp ...
- webpack2 前篇
webpack2 前篇 #webpack 前两天用了一天半时间琢磨了下webpack2,想起去年这时候,面对webpack1那样恶心的文档,前前后后搞了好几次才摸索清楚,那真是吐了. 划重点 其实we ...
- c3p0数据库连接池+mysql数据库基本使用方法
一般我们在项目中操作数据库时,都是每次需要操作数据库就建立一个连接,操作完成后释放连接.因为jdbc没有保持连接的能力,一旦超过一定时间没有使用(大约几百毫秒), 连接就会被自动释放掉. ...
- HDU1002——大整数加法
题目: I have a very simple problem for you. Given two integers A and B, your job is to calculate the S ...
- HAproxy部署配置
HAproxy部署配置 拓扑图 说明: haproxy服务器IP:172.16.253.200/16 (外网).192.168.29.140/24(内网) 博客服务器组IP:192.168.29.13 ...
- [技术]浅谈OI中矩阵快速幂的用法
前言 矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中,矩阵的运算是数值分析领域的重要问题. 基本介绍 (该部分为入门向,非入门选手可以跳过) 由 m行n列元素排列成的矩形阵列.矩阵里的 ...