在生产环境中,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

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

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

汉字在GBK编码中占2个字节,在UTF8编码中占3个字节

数字和英文字符在GBK和UTF8编码中都只占一个字节

汉字在UTF8编码和GBK编码不同,排序后顺序变化了。

原理分析:

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

比较逻辑:

获取字符串的第一个字节

根据UTF8的编码规则(附1),确定字符由几个字节组成

根据一定的算法算出字符的加权值(附2),比较大小;若不符合UTF8编码规范,认为是乱码,采用二进制比较(附3)

跳过步骤2返回的字节数,比较下一个字符。

附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)的风险,主要是索引或主键中包含字符串字段需要特别关注,如果字符串中确定只包含有数字和字符,则不会存在问题。

mysql gbk转utf8_MySQL字符集GBK转换到UTF8相关推荐

  1. mysql中gbk编码汉字和英文_MySQL字符集 GBK、GB2312、UTF8区别 解决 MYSQL中文乱码问题...

    MySQL中涉及的几个字符集 character-set-server/default-character-set:服务器字符集,默认情况下所采用的. character-set-database:数 ...

  2. mysql utf8和gbk的区别_MySQL字符集 GBK、GB2312、UTF8区别

    MySQL中涉及的几个字符集 character-set-server/default-character-set:服务器字符集,默认情况下所采用的. character-set-database:数 ...

  3. mysql gbk编码 转utf8_MySQLGBKUTF-8 编码转换

    MySQLGBKUTF-8 编码转换 前言: 第一次写教程, 其实算不得教程, 只是想总结个转换的手记如果中间有错误, 或者办法不够理想, 大家回贴研究下 另外, 我也希望我们论坛不仅仅作为闲聊的地方 ...

  4. mysql gbk_MySQL字符集 GBK、GB2312、UTF8区别 解决MYSQL中文乱码问题

    MySQL字符集 GBK.GB2312.UTF8区别 解决MYSQL中文乱码问题 更新时间:2012年08月27日 21:17:11   作者: MYSQL中文乱码问题原因有很多,脚本之家以前发布过很 ...

  5. MySQL数据库从GBK转换到UTF-8最简单解决方案(也适用于其它编码转换)

    MySQL数据库从GBK转换到UTF-8最简单解决方案(也适用于其它编码转换) 参考文章: (1)MySQL数据库从GBK转换到UTF-8最简单解决方案(也适用于其它编码转换) (2)https:// ...

  6. mysql 数据库是utf8 用cms gbk 可以吗_帝国cms编码GBK转换成UTF-8版教程方法

    注意事项: 转换前先备份下数据库以及d附件目录 转换步骤: 1.备份GBK版的数据库: 2.用Convertz编码转换软件将备份的数据库文件由GBK转为UTF-8: 3.将转换后的数据库恢复到UTF- ...

  7. mysql设置字符集gb2312_MySQL字符集 GBK、GB2312、UTF8區別 解決 MYSQL中文亂碼問題

    MySQL中涉及的幾個字符集 character-set-server/default-character-set:服務器字符集,默認情況下所采用的. character-set-database:數 ...

  8. 字符集GBK升级UTF8

    在生产环境中,数据库字符集因为各种原因需要升级,比如为了支持汉字,从latin1字符集升级到GBK,后面为了支持多个语言文字,需要将GBK升级到UTF8等.迁移过程网上有很多,我今天主要想讲下字符集转 ...

  9. 深入理解字符,字符集,gbk,utf8

    原创博客地址:深入理解字符,字符集,gbk,utf8 字符,字符集,字符编码概念 字节 1 字节(Byte)是计算机中数据存储的基本单元,一字节等于一个8位的比特,计算机中的所有数据,不论是保存在磁盘 ...

  10. EBCDIC 与 GBK 的字符编码及其转换(转)

    概览 有些用户在使用 AIX 时在字符编码方面遇到一些困惑,请看下面的场景: 1,用户用从 AIX 利用 FTP 客户端登录上 IBM i,切换到某个 Library/File,然后 get 其中的某 ...

最新文章

  1. 最新!2021 中国内地大学 ESI 排名出炉
  2. 文巾解题 56. 合并区间
  3. html5列表标签代码,HTML5列表标签和表格标签(示例代码)
  4. Angular实现图片点击缩放组件
  5. LeetCode算法入门- String to Integer (atoi)-day7
  6. 异域linux内核漏洞,Linux内核再现漏洞!这次11年后才发现
  7. ServletConfig讲解
  8. 军用装备温湿度循环测试,温湿度环境可靠性实验室GJB150A
  9. 在html页面中加入矢量图,在html中引用矢量图
  10. 人类首次捕获到反物质 500克能量可超过氢弹
  11. zimbra更换服务器域名
  12. 前端面试题之 对Promise的理解
  13. CSS:字体样式(字体系列、大小、加粗、风格、变形等)
  14. 网络存储服务器接显示器,Unraid下,单核显IGPU实现win10外接显示屏,显卡成功驱动...
  15. 万字详解大数据平台异地多机房架构实践
  16. KF、EKF、ESKF的区别与联系
  17. 内网渗透-window权限维持
  18. 【太虚AR_v0.1】使用教程 | 图像识别(多目标)
  19. 号卡推广管理系统源码 手机卡流量卡推广网站源码 带后台版本
  20. 小米手机 开发app python_python之小米应用商店爬虫

热门文章

  1. js日期减一个月_正正正国庆!折上再减!三亚/香格里拉/稻城/拈花湾,最低499元…...
  2. 基于STM32F103+涂鸦三明治的宠物自动喂食器
  3. 【Spring Boot】——集成JSON工具
  4. html5超级玛丽小游戏
  5. 地图标识符号大全_起名字大全男孩 男孩名字,起名字大全男孩
  6. 读书项目:ePub标准介绍
  7. CENTOS 7 完全硬盘安装及使用 1
  8. PUF论文整理2:2021_A_Novel_Modeling-Attack_Resilient_Arbiter-PUF_Design
  9. java的副语言_公共表达中,悄悄影响你的“副语言”
  10. C++ 中调用 Jscript 的函数