`

深入Mysql字符集设置

 
阅读更多

 

05 Jan 08 深入Mysql字符集设置

根据Chaos  Wang的PPT整理而成, 在此再次感谢Chaos Wang的此次TechTalk

基本概念

• 字符(Character)是指人类语言中最小的表义符号。例如’A'、’B'等;

• 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encoding)。例如,我们给字符’A'赋予数值0,给字符’B'赋予数值1,则0就是字符’A'的编码;

• 给定一系列字符并赋予对应的编码后,所有这些字符和编码对组成的集合就是字符集(Character Set)。例如,给定字符列表为{‘A’,'B’}时,{‘A’=>0, ‘B’=>1}就是一个字符集;

• 字符序(Collation)是指在同一字符集内字符之间的比较规则;

• 确定字符序后,才能在一个字符集上定义什么是等价的字符,以及字符之间的大小关系;

• 每个字符序唯一对应一种字符集,但一个字符集可以对应多种字符序,其中有一个是默认字符序(Default Collation);

• MySQL中的字符序名称遵从命名惯例:以字符序对应的字符集名称开头;以_ci(表示大小写不敏感)、_cs(表示大小写敏感)或_bin(表示按编码值比较)结尾。例如:在字符序“utf8_general_ci”下,字符“a”和“A”是等价的;

MySQL字符集设置

• 系统变量:

– character_set_server:默认的内部操作字符集

– character_set_client:客户端来源数据使用的字符集

– character_set_connection:连接层字符集

– character_set_results:查询结果字符集

– character_set_database:当前选中数据库的默认字符集

– character_set_system:系统元数据(字段名等)字符集

– 还有以collation_开头的同上面对应的变量,用来描述字符序。

• 用introducer指定文本字符串的字符集:

– 格式为:[_charset] ‘string’ [COLLATE collation]

– 例如:

• SELECT _latin1 ‘string’;

• SELECT _utf8 ‘你好’ COLLATE utf8_general_ci;

– 由introducer修饰的文本字符串在请求过程中不经过多余的转码,直接转换为内部字符集处理。

MySQL中的字符集转换过程

1. MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;

2. 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:

• 使用每个数据字段的CHARACTER SET设定值;

• 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);

• 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;

• 若上述值不存在,则使用character_set_server设定值。

3. 将操作结果从内部操作字符集转换为character_set_results。

图片1

常见问题解析

• 向默认字符集为utf8的数据表插入utf8编码的数据前没有设置连接字符集,查询时设置连接字符集为utf8

– 插入时根据MySQL服务器的默认设置,character_set_client、character_set_connection和character_set_results均为latin1;

– 插入操作的数据将经过latin1=>latin1=>utf8的字符集转换过程,这一过程中每个插入的汉字都会从原始的3个字节变成6个字节保存;

– 查询时的结果将经过utf8=>utf8的字符集转换过程,将保存的6个字节原封不动返回,产生乱码……

图片2

• 向默认字符集为latin1的数据表插入utf8编码的数据前设置了连接字符集为utf8

– 插入时根据连接字符集设置,character_set_client、character_set_connection和character_set_results均为utf8;

– 插入数据将经过utf8=>utf8=>latin1的字符集转换,若原始数据中含有\u0000~\u00ff范围以外的Unicode字 符,会因为无法在latin1字符集中表示而被转换为“?”(0x3F)符号,以后查询时不管连接字符集设置如何都无法恢复其内容了。

图片3

检测字符集问题的一些手段

• SHOW CHARACTER SET;

• SHOW COLLATION;

• SHOW VARIABLES LIKE ‘character%’;

• SHOW VARIABLES LIKE ‘collation%’;

• SQL函数HEX、LENGTH、CHAR_LENGTH

• SQL函数CHARSET、COLLATION

使用MySQL字符集时的建议

• 建立数据库/表和进行数据库操作时尽量显式指出使用的字符集,而不是依赖于MySQL的默认设置,否则MySQL升级时可能带来很大困扰;

• 数据库和连接字符集都使用latin1时虽然大部分情况下都可以解决乱码问题,但缺点是无法以字符为单位来进行SQL操作,一般情况下将数据库和连接字符集都置为utf8是较好的选择;

• 使用mysql C API时,初始化数据库句柄后马上用mysql_options设定MYSQL_SET_CHARSET_NAME属性为utf8,这样就不用显式地用 SET NAMES语句指定连接字符集,且用mysql_ping重连断开的长连接时也会把连接字符集重置为utf8;

• 对于mysql PHP API,一般页面级的PHP程序总运行时间较短,在连接到数据库以后显式用SET NAMES语句设置一次连接字符集即可;但当使用长连接时,请注意保持连接通畅并在断开重连后用SET NAMES语句显式重置连接字符集。

其他注意事项

• my.cnf中的default_character_set设置只影响mysql命令连接服务器时的连接字符集,不会对使用libmysqlclient库的应用程序产生任何作用!

• 对字段进行的SQL函数操作通常都是以内部操作字符集进行的,不受连接字符集设置的影响。

• SQL语句中的裸字符串会受到连接字符集或introducer设置的影响,对于比较之类的操作可能产生完全不同的结果,需要小心!

 

分享到:
评论

相关推荐

    深入Mysql字符集设置分析

    深入Mysql字符集设置分析,使用mysql的朋友可以参考下

    深入Mysql字符集设置[精华结合]

    深入Mysql字符集设置,建议大家看本文之前先看风雪之隅的文章,需要的朋友可以参考下

    深入Mysql字符集设置 图文版

    在mysql客户端与mysql服务端之间,存在着一个字符集转换器。 character_set_client =>gbk:转换器就知道客户端发送过来的是gbk格式的编码 character_set_connection=>gbk:将客户端传送过来的数据转换成gbk格式 ...

    mysqli_set_charset和SET NAMES使用抉择及优劣分析

    最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的”SET NAMES”和mysql_set_charset (mysqli_set_... 首先, 很多人都不知道”SET NAMES”到底是做了什么, 我之前的文章深入MySQL字符集设置中, 曾经介

    深入MYSQL字符数字转换的详解

    1.将字符的数字转成数字,比如’0’转成0可以直接用加法来实现例如:将pony表中的d 进行排序,可d的定义为varchar,可以这样解决select * from pony order by (d+0)2....字符集转换 : CONVERT(xxx USIN

    详解:Web应用程序中的字符集攻击 PPT

    本议题主要介绍在web安全中利用字符集实现攻击的几种形式,通过给出的几种实际环境中的攻击实例,分析了这些问题产生的本质原因和现在的web应用程序里处理字符集问题时经常出现的问题,从而更深入地了解和修正此类...

    老男孩Mysql DBA运维课程(19部全) Mysql DBA高级运维系列课程

    04-第四部-老男孩MySQL乱码问题及字符集实战(14节) 05-第五部-老男孩MySQL备份-增量备份及数据恢复基础实战(12节) 06-第六部-老男孩MySQL主从复制原理及实战部署(10节) 07-第七部-老男孩MySQL主从复制企业级...

    2017最新老男孩MySQL高级专业DBA实战课程全套【清晰不加密】,看完教程月入40万没毛病

    07-MySQL字符集介绍及生产常用字符集说明.avi 08-MySQL不同字符集区别及企业生产选择.avi 09-MySQL乱码原因开始系统影响揭秘.avi 10-MySQL上执行set names到底做了什么?.avi 11-MySQL命令带字符集导入到底做了什么...

    超级详细的MySQL数据库实战教程(包教包会)

    - 配置MySQL服务器,包括用户权限、字符集等。 ### 3. 数据库基础 - 创建和管理数据库。 - 理解数据库的基本概念,如表、字段、数据类型等。 ### 4. SQL语言基础 - 学习SQL(结构化查询语言)的语法和操作。 ...

    PHP和MySQL Web开发第4版pdf以及源码

    4.6.2 字符集和类 4.6.3 重复 4.6.4 子表达式 4.6.5 子表达式计数 4.6.6 定位到字符串的开始或末尾 4.6.7 分支 4.6.8 匹配特殊字符 4.6.9 特殊字符一览 4.6.10 在智能表单中应用 4.7 用正则表达式查找子...

    PHP和MySQL WEB开发(第4版)

    4.6.2 字符集和类 4.6.3 重复 4.6.4 子表达式 4.6.5 子表达式计数 4.6.6 定位到字符串的开始或末尾 4.6.7 分支 4.6.8 匹配特殊字符 4.6.9 特殊字符一览 4.6.10 在智能表单中应用 4.7 用正则表达式查找子字符串 4.8 ...

    深入浅出Hibernate源码

    在安装完mysql之后,请使用客户端或者phpmyadmin建立一个名为forum的mysql数据库,其字符集必须为UTF-8(见下面关于中文的说明,在phpmyadmin中应该选择utf8_general_ci)。另外还需要建立名为forum的用户,密码也为...

    PHP和MySQL Web开发第4版

    4.6.2 字符集和类 4.6.3 重复 4.6.4 子表达式 4.6.5 子表达式计数 4.6.6 定位到字符串的开始或末尾 4.6.7 分支 4.6.8 匹配特殊字符 4.6.9 特殊字符一览 4.6.10 在智能表单中应用 4.7 用正则表达式查找子...

    深入理解用mysql_fetch_row()以数组的形式返回查询结果

    同mysql_result()一样,mysql_fetch_row()也可以用来获取查询结果集,其区别在于函数的返回值不是一个字符串,而是一个数组。函数定义如下。复制代码 代码如下:array mysql_fetch_row(int result) 参数说明如下。...

    深入浅出Hibernate

    具体进行的处理为全程采用UTF-8编码. 1,mysql创建时,字符集必须选择UTF-8 2,在mysql jdbc连接的url中,必须指定采用utf-8 encoding。 jdbc:mysql://localhost/forum?useUnicode=true&characterEncoding...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    21.1.1 常用字符集 610 21.1.2 对乱码产生过程的分析 612 21.2 中文乱码问题的解决方案 614 21.3 使用过滤器解决中文问题 616 21.4 让tomcat支持中文文件名 620 21.5 国际化与本地化 621 21.5.1 locale 621.. ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    21.1.1 常用字符集 610 21.1.2 对乱码产生过程的分析 612 21.2 中文乱码问题的解决方案 614 21.3 使用过滤器解决中文问题 616 21.4 让tomcat支持中文文件名 620 21.5 国际化与本地化 621 21.5.1 locale 621.. ...

Global site tag (gtag.js) - Google Analytics