深入了解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

时间: 2024-10-10 19:38:54

深入了解mysql数据传输编码原理的相关文章

Mysql编码, Mysql编码流程, Mysql编码顺序, Mysql编码原理, Mysql编码修改依据

编码查看方式以及解释说明: 需要以root用户身份登陆才可以查看数据库编码方式(以root用户身份登陆的命令为:>mysql -u root –p,之后两次输入root用户的密码),查看数据库的编码方式命令为: >show variables like 'character%'; +--------------------------+----------------------------+ | Variable_name | Value | +-----------------------

MySQL的字符编码体系(二)——数据传输编码

MySQL的字符编码体系可以分成两部分:一部分是关于数据库服务器本身存储数据表时如何管理字符数据的编码:另一部分是关于客户端与数据库服务器传输数据如何编码.上一篇MySQL的字符编码体系(一)--数据存储编码讨论了数据存储编码,本篇讨论数据传输编码. MySQL的客户端可以分为两种:一种就是用C语言写的官方客户端--MySQL命令程序:一种就是平常程序员使用JDBC等connector API写成的客户端.这里只讨论第一种. Windows客户端 MySQL命令程序在Windows和Linux系

MySQL字符集编码

MySQL字符集编码总结 之前内部博客上凯哥分享了一篇关于mysql字符集的文章,之前我对mysql字符集一块基本没有深究过,看到凯哥文章后有些地方有点疑惑,遂自己去看了mysql的官方文档,并参考了凯哥的文章,总结了这篇博文.本文主要是对mysql常见的字符集问题进行整理,如有错误,请大家指正. 1.MySQL字符集编码简介 谈到字符集,总会跟编码扯上关系,有关字符集和编码的理论知识请参见我之前的文章.MySQL内部是支持多种字符集的,这里就不再严格区分字符集和编码的概念了.同时,MySQL中

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

Mysql储存过程是一组为了完成特定功能的SQL语句集,经过编译之后存储在数据库中,当需要使用该组SQL语句时用户只需要通过指定储存过程的名字并给定参数就可以调用执行它了,简而言之就是一组已经写好的命令,需要使用的时候拿出来用就可以了.想要快速的了解Mysql储存过程吗,就一同看一下下文的"Mysql储存过程-原理.语法.函数详细说明"吧! 一.Mysql储存过程简介:储存过程是一个可编程的函数,它在数据库中创建并保存.它可以有SQL语句和一些特殊的控制结构组成.当希望在不同的应用程序

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

摘要: 第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1.简单介绍B-tree B+ tree树 2.MyisAM索引结构 3.Annode索引结构 4.MyisAM索引与InnoDB索引相比较 第三部分:MYSQL优化 1.表数据类型选择 2.sql语句优化 (1)     最左前缀原则 (1.1)  能正确的利用索引 (1.2)  不能正确的利用索引 (1.3)  如果一个查询where子句中确实不需要password列,那就用“补洞”. (1.4)  like (2)

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

最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主要介绍MySQL5.7 SSL连接加密功能.如何使用?以及使用SSL的一些注意点. 我们知道,MySQL5.7之前版本,安全性做的并不够好,比如安装时生成的root空密码账号.存在任何用户都能连接上的test库等,导致数据库存在较大的安全隐患.好在5.7版本对以上问题进行了一一修复.与此同时,MyS

PHP和MYSQL的编码问题

http://blog.csdn.net/martinkro/article/details/5352474 1 MYSQL中的字符集概念  Mysql的字符集里有两个概念,一个是"Character set(字符集)",另一个是"Collations".1.1 Collations  Collations翻成中文是"校验",在网页开发的过程中,这个词汇,只在Mysql里使用,主要作用是指导Mysql对字符的比较,比如, ASCII字符集里,Co

Linux下使用MySQL——忘记root密码及修改MySQL默认编码

概述: 本博客不再对MySQL的语法进行讲解和说明,想了解或熟悉的朋友请自行百度或Google学习.本博客主要是针对MySQL除语法之外的总结,希望能够也能帮助到你. 1.CentOS6.x下MySQL忘记root密码解决方法 Ⅰ. 修改MySQL的登录设置 # vim /etc/my.cnf 在[mysqld]段中加上一句:skip-grant-tables Ⅱ. 重启服务 # service mysqld restart Ⅲ. 登录Mysql,修改密码信息 # mysql mysql> US

Atitit.Base64编码原理与实现设计

Atitit.Base64编码原理与实现设计 1. Base64编码1 1.1. 为什么要用自己的base64编码方案1 2. Base64编码由来1 3. Base64编码原理1 3.1. 具体来说,转换方式可以分为四步:2 3.2. 注意2 3.3. Padding3 4. URL安全的Base64编码3 1. Base64编码 1.1. 为什么要用自己的base64编码方案 防止apache codec  jdk的jar冲突. 2. Base64编码由来 Base64最早是用来解决电子邮件