一、基本概念(这里引用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数据传输编码原理的更多相关文章

  1. MYSQL索引结构原理、性能分析与优化

    [转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...

  2. MySQL字符集编码

    MySQL字符集编码总结 之前内部博客上凯哥分享了一篇关于mysql字符集的文章,之前我对mysql字符集一块基本没有深究过,看到凯哥文章后有些地方有点疑惑,遂自己去看了mysql的官方文档,并參考了 ...

  3. MYSQL转换编码的解决方法

    MYSQL转换编码的解决方法 一.在utf8的mysql下 得到中文‘游客’的gbk下的16进制编码 mysql> SELECT hex(CONVERT( '游客' USING gbk )); ...

  4. 你的MySQL服务器开启SSL了吗?SSL在https和MySQL中的原理思考

    最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主 ...

  5. MySQL 储存过程-原理、语法、函数详细说明

    Mysql储存过程是一组为了完成特定功能的SQL语句集,经过编译之后存储在数据库中,当需要使用该组SQL语句时用户只需要通过指定储存过程的名字并给定参数就可以调用执行它了,简而言之就是一组已经写好的命 ...

  6. 【转】由浅入深探究mysql索引结构原理、性能分析与优化

    摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1.简单介绍B-tree B+ tree树 2.MyisAM索引结构 3.Annode索引结构 4.MyisAM索引与Inno ...

  7. H264编码原理以及I帧、B和P帧详解, H264码流结构分析

    H264码流结构分析 http://blog.csdn.net/chenchong_219/article/details/37990541 1.码流总体结构: h264的功能分为两层,视频编码层(V ...

  8. xss的编码原理

    把以前的笔记翻出来整理一下 最前方 xss如何选用编码原理,为什么 找到的挺清楚的文章了:https://www.cnblogs.com/p0laris/p/11898322.html浏览器解析有两种 ...

  9. mysql utf8编码

    做微信项目,报错 "Incorrect string value: '\\xF0\\x9F\\x98\\x8B' for column 'nickname' at row 1" 原 ...

随机推荐

  1. 父(Spring)子(SpringMVC)容器之初解篇

    Spring和SpringMVC作为Bean管理容器和MVC层的默认框架,已被众多WEB应用采用,而在实际开发中,由于有了强大的注解功能,很多基于XML的配置方式已经被替代,但在实际项目中,我们经常会 ...

  2. redhat nginx随机启动脚本

    开机自动启动nginx 1.    扔脚本进去/etc/init.d/ 2.    授权     chmod +x nginx 3.    一旦抛出:binsh^M错误就执行编码改写     设置do ...

  3. lombok的简单介绍和使用方法

    这是上周在群里发现有人推荐lombok,他说是神器,当时就引起了我的好奇,然后下班回来我就看了看官网介绍(菜鸟英语水平),这就是难点了,然后就是大概了解了一下,就在网上查了查相关资料,周末的时候自己试 ...

  4. [vijos 1642]班长的任务 [树形dp]

    背景 十八居士的毕业典礼(1) 描述 福州时代中学2009届十班同学毕业了,于是班长PRT开始筹办毕业晚会,但是由于条件有限,可能每个同学不能都去,但每个人都有一个权值,PRT希望来的同学们的权值总和 ...

  5. Maven “Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.4:create...”问题总结

    今天学习Maven的过程中,一直遇到一个问题:用maven指令构建新项目时,一直报错,用的 Maven 3.2 , JDK 6. 构建的命令: 错误信息: 解决方案: 在StackOverFlow上找 ...

  6. Struts2 动态调用方法

    struts2动态调用方法有两种方式 方式一:用通配符进行调用: Action方法: package com.bjyinfu.struts.actions; public class CatchDyn ...

  7. FaceRank,最有趣的 TensorFlow 入门实战项目

    FaceRank,最有趣的 TensorFlow 入门实战项目 TensorFlow 从观望到入门! https://github.com/fendouai/FaceRank 最有趣? 机器学习是不是 ...

  8. Spring-mybatis没有了XXXmapper.java和Dao的实现类还有Service的实现类

    对于刚学过框架的同学可能知道,mybatis有两种主要的配置文件: SqlMapConfig.xml(mybatis全局配置文件,名称不固定,用来配置运行环境(数据源.事务) XXXmapper.xm ...

  9. Linux(1)目录

    Linux目录 / :根目录, 一般只存放目录, 在Linux下只有一个根目录. 所有的东西都是从这里开始 /bin, /usr/bin :可执行的二进制文件目录, 如常用的ls, tar, mv, ...

  10. 【前端,干货】react and redux教程学习实践(二)。

    前言 这篇博文接 [前端]react and redux教程学习实践,浅显易懂的实践学习方法. ,上一篇简略的做了一个redux的初级demo,今天深入的学习了一些新的.有用的,可以在生产项目中使用的 ...