热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

MySQL字符集GBK转换到UTF8

在生产环境中,MySQL数据库字符集因为各种原因需要升级,比如为了支持汉字,从latin1字符集升级到GBK,后面为了支持多个语言文字

在生产环境中,MySQL数据库字符集因为各种原因需要升级,比如为了支持汉字,从latin1字符集升级到GBK,后面为了支持多个语言文字

在生产环境中,MySQL数据库字符集因为各种原因需要升级,比如为了支持汉字,从latin1字符集升级到GBK,后面为了支持多个语言文字,需要将GBK升级到UTF8等。迁移过程网上有很多,我今天主要想讲下字符集转换后,可能对业务产生的影响,我以GBK转换到UTF8为例说明。

主要有两点:

1.汉字在GBK编码中占2个字节,在UTF8编码中占3个字节,而mysql的索引要求总长度不超过767个字节,因此索引字符数会被缩短(383->255),特别的,对于唯一索引,要求索引字段长度小于256个字符。

2.编码转换后,导致字段排序发生变化。

这篇文章主要为了说明编码转换后,字段排序如何受影响,会结合mysql源代码给出原因和分析。首先看测试用例,假设cmp_t(GBK编码)和cmp_t2(UTF8编码)分别是迁移前后的表。

测试用例:

操作

cmp_t(GBK)

cmp_t2(UTF8)

1

GBK表:

select c1,hex(c1) from cmp_t;

UTF8表:

select c1,hex(c1) from cmp_t2;

+------+---------+

| c1 | hex(c1) |

+------+---------+

| 一 | D2BB

| 二 | B6FE

| 三 | C8FD

| a | 61

| 1 | 31

+------+---------+

+------+---------+

| c1 | hex(c1) |

+------+---------+

| 一 | E4B880

| 二 | E4BA8C

| 三 | E4B889

| a | 61

| 1 | 31

+------+---------+

2

GBK表:

select c1,hex(c1) from cmp_t where c1>’a’ order by c1;

UTF8表:

select c1,hex(c1) from cmp_t2 where c1>’a’ order by c1;

+------+---------+

| c1 | hex(c1) |

+------+---------+

| | B6FE |

| | C8FD

| | D2BB

+------+---------+

+------+---------+

| c1 | hex(c1) |

+------+---------+

| | E4B880

| | E4B889

| | E4BA8C

+------+---------+

从上面操作返回的结果我们可以得到以下几点信息:

原理分析:

Mysql利用sortcmp函数对字符串进行比较,对于GBK的字符串和UTF8的字符串分别采用接口my_strnncollsp_gbk和my_strnncollsp_utf8比较,这两个函数分别在ctype-gbk.c和ctype-utf8.c中实现,两个函数实现逻辑类似,只是各有自己一套比较大小的规则,下面我主要描述下my_strnncollsp_utf8的比较逻辑和比较大小的规则。

比较逻辑:

附1:【接口: my_utf8_uni】

根据UTF8编码规则,符合编码规范的字符占用1-6个字节。

取字符串第一个字节 s

if s<0x80

表示字符占1个字节

elif s<0xe0

表示字符占2个字节

elif s<0xf0

表示字符占3个字节

else s<0xf8

表示字符占4个字节

elif s<0xfc

表示字符占5个字节

elif s<0xfe

表示字符占6个字节

英文字符和数字字符编码兼容ASCII,编码值小于0x80,因此都只占1个字节;汉字的utf8编码的首字节都在[0xe0,0xf0]之间,所以占3个字节。

附2:utf8编码比较大小规则

value = ((s[0] & 0x0f) <<12)| ((s[1] ^ 0x80) <<6) | (s[2] ^ 0x80)

s[0],s[1],s[2]表示组成汉字的三个字节,对参与比较的汉子字符进行计算得到value1和value2,通过比较value1和value2的大小,判断字符大小。

附3:二进制比较【接口: bincmp】

memcmp函数比较,即逐字节比较。

因此,如果业务上面需要依赖汉字比较的场景,需要考虑字符集升级(GBK->UTF8)的风险,主要是索引或主键中包含字符串字段需要特别关注,,如果字符串中确定只包含有数字和字符,则不会存在问题。

本文永久更新链接地址

推荐阅读
  • 本文详细探讨了不同SQL数据库管理系统(DBMS)在限制输出结果、拼接字段和日期时间处理方面的函数差异。通过具体示例,帮助读者理解并掌握如何在不同DBMS中实现相同功能。 ... [详细]
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 解决PHP与MySQL连接时出现500错误的方法
    本文详细探讨了当使用PHP连接MySQL数据库时遇到500内部服务器错误的多种解决方案,提供了详尽的操作步骤和专业建议。无论是初学者还是有经验的开发者,都能从中受益。 ... [详细]
  • 在哈佛大学商学院举行的Cyberposium大会上,专家们深入探讨了开源软件的崛起及其对企业市场的影响。会议指出,开源软件不仅为企业提供了新的增长机会,还促进了软件质量的提升和创新。 ... [详细]
  • 本文探讨了适用于Spring Boot应用程序的Web版SQL管理工具,这些工具不仅支持H2数据库,还能够处理MySQL和Oracle等主流数据库的表结构修改。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • Windows 系统下 MySQL 8.0.11 的安装与配置
    本文详细介绍了在 Windows 操作系统中安装和配置 MySQL 8.0.11 的步骤,包括环境准备、安装过程以及后续配置,帮助用户顺利完成数据库的部署。 ... [详细]
  • 本文深入探讨了如何通过调整InnoDB的关键配置参数来优化MySQL的随机IO性能,涵盖了缓存、日志文件、预读机制等多个方面,帮助读者全面提升数据库系统的性能。 ... [详细]
  • 本文详细介绍如何下载并安装MySQL数据库(5.7.10版本),以及配置Navicat管理工具(免费版)。通过本指南,您将了解从下载到安装的完整流程,并掌握基本的数据库管理技能。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
  • 本文探讨了在处理大量物联网设备时,如何合理设计关系型数据库来高效记录设备的上下线历史,确保数据的可维护性和扩展性。 ... [详细]
author-avatar
古韵卡次
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有