根据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。

常见问题解析

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

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

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

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

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

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

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

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

• 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字符集设置的更多相关文章

  1. Mysql字符集设置

    转 基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如’A'.’B'等:• 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encodi ...

  2. MySQL 字符集设置

    /*************************************************************************** * MySQL 字符集设置 * 说明: * 数 ...

  3. Mysql字符集设置 2 图

    基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如'A'.'B'等: • 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encodin ...

  4. mysql字符集设置注意事项

    mysql字符集设置必须是在具体的某一个数据库情况下才能进行设置 否则会报错.

  5. MySQL字符集设置及字符转换(latin1转utf8)

    MySQL字符集设置及字符转换(latin1转utf8) http://blog.chinaunix.net/uid-25266990-id-3344584.html  MySQL字符集设置及字符转换 ...

  6. [mysql]深入Mysql字符集设置[转载]

    http://www.laruence.com/2008/01/05/12.html 基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如’A'.’B'等: • 给定一系列字符, ...

  7. mysql字符集设置utf-8

    mysql字符集设置utf-8 mysql修改环境的默认字符集为utf-8(当然你也可以设置成别的,国际点还是utf-8好) 如果不把mysql字符集统一下,后面还是有点麻烦的 首先得在服务里关掉my ...

  8. docker mysql 文件挂载和MySQL字符集设置

    原文:docker mysql 文件挂载和MySQL字符集设置 docker run -p 3306:3306 --name mysql -v /usr/local/mysql/my.cnf:/etc ...

  9. mysql 字符集设置查看

    1.列出MYSQL支持的所有字符集: SHOW CHARACTER SET; 2.当前MYSQL服务器字符集设置 SHOW VARIABLES LIKE 'character_set_%'; 3.当前 ...

随机推荐

  1. 正确的在循环list的时候删除list里面的元素

    s = [1,2,3,4,5] for i in s: s.remove(i) print(s)   输出结果:[2, 4] 1.当第一次删除后,后面的元素会前移,此时s=[2,3,4,5], 2.然 ...

  2. CodeForces 800B Volatile Kite(点与直线的距离)(Java 实现)

    CodeForces 800B Volatile Kite(点与直线的距离)(Java 实现) 传送门 如果想要一个凸多边形不退化为凹多边形,那么任意的相邻的三个点必然最多形成一条直线.因此我们可以求 ...

  3. ajax加载本地html文件出现 XMLHttpRequest cannot load的问题

    谷歌浏览器ajax加载本地html文件出现 XMLHttpRequest cannot load的问题(火狐中不会出现这问题) Cross origin requests are only suppo ...

  4. Ubuntu查看隐藏文件夹的方法

    比如要查看当前用户目录下的隐藏文件夹 进入/home/jim目录,使用快捷键Ctrl+H,即可显示隐藏文件夹,如果要关闭,再次按Ctrl+H即可. GUI操作如下所示: 进入文件夹,左上角->查 ...

  5. Luca Canali

    https://github.com/LucaCanali http://cern.ch/canali/

  6. Node.js 博客实例(三)添加文件上传功能

    原教程 https://github.com/nswbmw/N-blog/wiki/_pages的第三章 上传文件眼下有三种方法: 使用 Express 自带的文件上传功能,不涉及数据库 使用 For ...

  7. gem5: 使用ruby memory system中的mesh结构 出现AssertionError错误

    问题:在使用ruby memory system中的mesh结构測试时,出现例如以下错误: Traceback (most recent call last): File "<stri ...

  8. ftk学习记(输入框篇)

    [ 声明:版权全部.欢迎转载.请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 昨天讲了进度条,我们还是看看它的运行效果是怎么样的.截图例如以下, 进度条使用的情况还是比較多的 ...

  9. 【Cocos2dx游戏开发】CCNotificationCenter传递消息和数据

    在开发游戏的时候我们经常需要在层与层之间.场景与场景之间传递数据和消息,Cocos2dx框架应用观察者模式为我们封装了一个CCNotificationCenter类,也叫消息通知中心,它也是一个单例类 ...

  10. 《C# 6.0 本质论》 阅读笔记

    <C# 6.0 本质论> 阅读笔记   阅读笔记不是讲述这本书的内容,只是提取了其中一部分我认为比较重要或者还没有掌握的知识,所以如果有错误或者模糊之处,请指正,谢谢! 对于C# 6.0才 ...