前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >问题分析:什么导致mysql乱码?

问题分析:什么导致mysql乱码?

原创
作者头像
王昂
修改2019-11-16 16:48:23
2.1K0
修改2019-11-16 16:48:23
举报
文章被收录于专栏:Andy的技术专栏Andy的技术专栏

之前出现过一些因为mysql编码使用不正确,导致出现页面乱码的bug,比如utf8不支持Emoji表情等等。这里对乱码问题做下分析,沉淀下来避免再次出现

目录

  1. 先了解3个概念:字符集、编码、乱码
  2. 常见的字符集编码有哪些?
  3. 详解Unicode字符集细节
  4. 怎么查看mysql支持哪些字符集/字符序?
  5. 怎么预防mysql乱码问题?

先了解3个概念:字符集、编码、乱码

为什么要有字符集编码?

一切都是因为电脑不识字,只认识数字(010101)

故我们需把字符(如'A'这个字符)通过一张字符集表,映射成一个数字ID,编码成2进制存储在电脑内

字符集和编码是两码事

Unicode 是「字符集」

UTF-8 是「编码规则」,是Unicode编码的一种实现

字符集:只规定字符的数字编码,即为每一个「字符」分配唯一的 ID(学名为码位 / 码点 / Code Point)

编码规则:把数字编码转为二进制形式,即将「码位」转换为字节序列的规则(可理解为 加密/解密 的过程)

乱码是怎么产生的?要怎么解决?

写入选择的编码方式,和读取选择的编码方式不一致

故要解决乱码问题,核心思路是让读取的编码方式与写入的一致

常见的字符集编码有哪些?

程序员得掌握哪些字符集编码?

大千世界,语言千万种,字符集编码也非常多,但建议只了解最核心4种就够了,甚至只了解Unicode/UTF-8就够了

英文的终极方案:ASCII

大名鼎鼎的ASCII是最早的美国国家标准,单字节编码,共收录128个字符,统一规定了英文常用符号编码

mysql默认编码:Latin1/ISO 8859-1

单字节编码,字符范围很窄,最多表示字符范围是0-255,应用于英文,不支持中文

中文编码的一波三折:GB2312/GBK

ASCII不支持中文,为了解决中文编码问题,中国国家标准总局发布汉字编码规范,但也是一波三折:

  1. 第1次发布GB2312,双字节等宽编码,支持简体汉字字符
  2. 第2次发布GBK,双字节等宽编码,多支持繁体字和生僻字
  3. 第3次发布GB18030,变长编码,收录了所有Unicode3.1中的字符

最终统一的“万国码”:Unicode/UTF-8

像GBK一样,每个国家搞一套显然全世界是没法统一的。为了彻底解决这个问题,于是Unicode(万国码)诞生了

Unicode记录着世界上所有字符对应的一个数字,仅仅只是一个字符集

为了较好解决Unicode编码问题,UTF-8(1-4字节变长)和UTF-16(2/4字节变长)两种较流行的编码方式诞生了

详解Unicode字符集细节

Code Points

Unicode把每个字符分配的唯一ID叫做码点(Code Points),Unicode共有111万+个码点,现在大概已分配了11万个

Code Space和Code Plane(BMP)

所有码点组成代码空间(Code Space),Unicode把代码空间分成了17个代码平面(Code Plane),编号为#0到#16,每个代码平面包含65536(2^16)个码点,如下图所示:

Unicode.png
Unicode.png
  1. Plane#0 BMP(Basic Multilingual Plane):最重要平面,包含大部分常用字符,比如ASCII,汉字等
  2. Plane#1 SMP:古老的文字,不常用
  3. Plane#2 SIP:BMP中没有包含汉字
  4. Plane#14 SSP:非图形字符

具体Unicode编码表

网上很多工具,这里就不展开,可以等到出现乱码再抠出存储二进制去查一下:

https://www.cnblogs.com/csguo/p/7401874.html

怎么查看mysql支持哪些字符集/字符序

查看支持字符集

方法1:SHOW CHARACTER SET;

方法2:SELECT * FROM information_schema.CHARACTER_SETS;

查看字符集.png
查看字符集.png

查看支持字符序

字符序定义了字符编码的比较规则,一个字符集对应至少一种字符序(一般是1对多),比如utf8mb4_unicode_ci就是utf8mb4字符集其中一种字符序

方法1:SHOW COLLATION;

方法2:SELECT * FROM information_schema.COLLATIONS;

查看字符序.png
查看字符序.png

怎么预防mysql乱码问题?

查看和mysql编码相关的配置

  1. 查看链接编码 character_set_client、character_set_connection、character_set_results SHOW VARIABLES LIKE '%character%';
    查看链接/服务编码.png
    查看链接/服务编码.png
  2. 查看mysql服务编码 character_set_server
  3. 查看数据库编码 SELECT * FROM information_schema.SCHEMATA WHERE schema_name="ONLINE_EDU_TEST";
    查看数据库编码.png
    查看数据库编码.png
  4. 查看表编码 SHOW TABLE STATUS FROM ONLINE_EDU_TEST LIKE 't_online_class_time';
    查看表编码.png
    查看表编码.png
  5. 查看字段编码(一般看表的编码,某个字段特殊设置比较少) SHOW FULL COLUMNS FROM edu_comment_stored_backup_0;
    查看字段编码.png
    查看字段编码.png

设置和mysql编码相关的配置

  1. 设置链接编码 执行SQL命令:mysql -h xx -P xx -uxx -p --default-character-set='utf8' 调用mysqlclient:sConn.pConn->set_option(new mysqlpp::SetCharsetNameOption("utf8mb4"));
  2. 设置mysql服务编码 启动服务时指定:mysqld --character-set-server=latin1 --collation-server=latin1_swedish_ci 配置文件指定(my.cnf):mysql default-character-set=utf8 运行时修改,但重启失效:SET character_set_server = utf8 ;
  3. 设置数据库编码 创建db:CREATE DATABASE db_name DEFAULT CHARACTER SET charset_name 修改db:ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
  4. 设置表编码 创建表:CREATE TABLE tbl_name (column_list) DEFAULT CHARACTER SET charset_name 修改表:ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  5. 设置字段编码 创建字段:ALTER TABLE test_table ADD COLUMN char_column VARCHAR(25) CHARACTER SET utf8; 修改字段:ALTER TABLE test_table CHANGE column_name VARCHAR(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

关于mysql乱码的一些实践经验

  1. 保证链接、库、表、字段统一编码方式
  2. 不依赖默认编码,在客户端创建链接和建表的时候,统一显示指定编码。防止迁移DB等场景,因为系统默认编码不同导致乱码
  3. 统一使用utf8_mb4,不用utf8和gbk。因为3个字节utf8只支持unicode的BMP,不支持特殊Unicode编码(补充平面),如Emoji表情;gbk更多在中文环境中使用,较局限。此外: utf8_mb4支持版本:>=mysql5.5.3 utf8_mb4兼容utf8:4个字节utf8_mb4是utf8超集

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 先了解3个概念:字符集、编码、乱码
    • 为什么要有字符集编码?
      • 字符集和编码是两码事
        • 乱码是怎么产生的?要怎么解决?
        • 常见的字符集编码有哪些?
          • 英文的终极方案:ASCII
            • mysql默认编码:Latin1/ISO 8859-1
              • 中文编码的一波三折:GB2312/GBK
                • 最终统一的“万国码”:Unicode/UTF-8
                • 详解Unicode字符集细节
                  • Code Points
                    • Code Space和Code Plane(BMP)
                      • 具体Unicode编码表
                      • 怎么查看mysql支持哪些字符集/字符序
                        • 查看支持字符集
                          • 查看支持字符序
                          • 怎么预防mysql乱码问题?
                            • 查看和mysql编码相关的配置
                              • 设置和mysql编码相关的配置
                                • 关于mysql乱码的一些实践经验
                                相关产品与服务
                                云数据库 SQL Server
                                腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                                领券
                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                                http://www.vxiaotou.com