从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • 计算机简史

  • 数字电路

  • 计算机组成原理

    • 计算机组成原理(北大-陆俊林)

    • 字符编码入门

      • 简单聊聊计算机之中的时间
      • 简单聊聊字符编码
      • ASCII 字符表和说明
      • ASCII 的 SOH 的用处
      • 回车和换行
      • 汉字是怎么编码的
      • 简单聊聊 Unicode
      • 手持两把锟斤拷,口中疾呼烫烫烫
      • 数据库与编码
        • 编码的重要性
        • 演示
        • 小结
        • 参考
      • 编程语言与字符编码
      • URL 编码
      • Base64 编码
      • 字符编码小结
      • 一些有趣的代码注释
  • 操作系统

  • Linux

  • 计算机网络

  • 数据库

  • 编程工具

  • 装机

  • 计算机基础
  • 计算机组成原理
  • 字符编码入门
2022-12-21
目录

数据库与编码

# 19.数据库与编码

以 MySQL 为例。在 MySQL 中,utf8 编码并不是真正意义上的 utf8,而是 utf8mb3。utf8mb3 支持的字符集是 0~65535 之间的 BMP 的字符,最多支持 3 个字节,一些生僻字和 emoji 是不支持。

以 MySQL 为例。在 MySQL 中,utf8 编码并不是真正意义上的 utf8,而是 utf8mb3。utf8mb3 支持的字符集是 0~65535 之间的 BMP 的字符,最多支持 3 个字节,一些生僻字和 emoji 是不支持。

这会导致什么问题呢?如果你数据库使用的是 utf8mb3 编码,那么在 insert 一些 4 字节的字符的时候,会报错:

insert into t (name) value('😂')
SQL 错误 [1366] [HY000]: Incorrect string value: '\xF0\x9F\x98\x82' for column 'name' at row 1

insert into t (name) value('𡋾')
SQL 错误 [1366] [HY000]: Incorrect string value: '\xF0\xA1\x88\xBE' for column 'name' at row 1
1
2
3
4
5

‍ 其实,这并不是 MySQL 自己的问题,而是 Unicode 在一开始的时候就没确定好到底用几个字节存储,当时的方案并不完善;等到了后来,Unicode 标准才正式发布,确定了存储方案。

于是,在 2010 年,MySQL 发布了 MySQL 5.53,在创建数据库时可以用一个新的字符集 utf8mb4,支持 4 个字节的字符

官方文档醒目的提醒了大家说 utf8mb3 会在未来的版本中删除,并建议用户优先使用 utf8mb4。所以在创建数据库的时候,确保的使用是 utf8mb4,而不是 utf8mb3。 ‍ 官方的一些说明:MySQL :: MySQL 8.0 Reference Manual :: 10.9.2 The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding) (opens new window)

Applications that use UTF-8 data but require supplementary character support should use utf8mb4​ rather than utf8mb3​ (see Section 10.9.1, “The utf8mb4 Character Set (4-Byte UTF-8 Unicode Encoding)” (opens new window)).

可以通过查看数据库的建表语句来检查:

show create database 数据库名\G;
-- 例如
mysql> show create database dblog\G;
*************************** 1. row ***************************
       Database: dblog
Create Database: CREATE DATABASE `dblog` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */
1 row in set (0.00 sec)
1
2
3
4
5
6
7

笔者在 MySQL 8.0.27 下尝试了下,默认都是用的 utf8mb4 编码了,而在很久之前,默认编码是 utf8mb3。

如果是早期的数据库表,有需求要兼容 4 个字节的字符的话,可以修改对应的字段的编码或数据库的编码。

# 编码的重要性

编码是一件非常重要的事情。现代很多系统都要求支持 Unicode。如果不支持,有什么后果呢?

举个例子,如果某个人名字带有生僻字,银行的系统不支持,那么这个客户就不能去该银行做业务,直接损失了一名客户。 ‍ 例如:在 有没有谁的朋友名字中含有“䶮”字的? - 知乎 (opens new window) 里有人提到:

本人有两张储蓄卡,招商和工商,招商的户名是某䶮,工商银行的户名是某(YAN3),亲身经历证明:招商储蓄卡无法变更为公积金联名卡,主要原因是姓名不一致,因此肯定没有办法提取公积金 ‍ 一个名字叫“䶮”的人的苦恼:开不了银行账户,用不了微信、支付宝 (opens new window)

近日,多位人士向记者表示,自己的名字中含有 “䶮”等汉字,在办理公积金、银行卡、第三方支付、手机卡等金融、通信业务时,名字无法被验证,导致业务无法办理。

甚至,因为没法申请银行账户,微信、支付宝也拒绝使用,有的银行建议名字带有“䶮”字的用户改回繁体字“龑”。

生僻字带来金融交易中的麻烦,这一情况并不鲜见。 ‍

# 演示

实践出真知,我们来演示下,本文是在 Windows 下的 MySQL 5 演示。

首先创建一个数据库,并指定字符集

mysql> create database testunicode default character set utf8 collate utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
1
2

‍ 创建完后,可以检查下该数据库的编码

mysql> show create database testunicode;
+------------+--------------------------------------------------------+
| Database    | Create Database                                                      |
+------------+--------------------------------------------------------+
| testunicode | CREATE DATABASE `testunicode` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+-------------+--------------------------------------------------------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7

‍ 使用该数据库并创建表,可以看到该表的默认编码是 UTF8

mysql> use testunicode;
Database changed

mysql> create table t (name varchar(50));
Query OK, 0 rows affected (0.25 sec)

mysql> show create table t
CREATE TABLE `t` (
  `name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1
2
3
4
5
6
7
8
9
10

‍ 尝试 insert 一个 emoji,确实有报错:

insert into t (name) value('😂')

SQL 错误 [1366] [HY000]: Incorrect string value: '\xF0\x9F\x98\x82' for column 'name' at row 1
1
2
3

‍ 接下来我们尝试更换字符集,并创建一个新表:

mysql> ALTER DATABASE `testunicode`
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_bin;

mysql> create table tu (name varchar(50))

mysql> show create table t
CREATE TABLE `t` (
  `name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1
2
3
4
5
6
7
8
9
10

‍ 尝试重新 insert,结果是能成功 insert(没有报错就是成功):

mysql> insert into tu (name) value('😂')
1

# 小结

虽然目前 MySQL 默认都是使用 utf8mb4 了,但一些早期的项目还是使用的 utf8mb3,希望读者们如果遇到了该编码问题能有思路,知道是怎么回事、怎么修复。

触类旁通,其他关系型数据库,例如 Oracle 等,也需要考虑编码问题 ‍

# 参考

英文版(需科学上网)In MySQL, never use “utf8”. Use “utf8mb4”. | by Adam Hooper | Medium (opens new window)

中文版:记住,永远不要在 MySQL 中使用“utf8”_数据库_Adam Hooper_InfoQ 精选文章 (opens new window)

一个名字叫“䶮”的人的苦恼:开不了银行账户,用不了微信、支付宝 (opens new window)

曝光 MySQL 的 一个坑,不要再使用 UTF-8 了? (opens new window) ‍

上次更新: 2025/5/5 17:15:09
手持两把锟斤拷,口中疾呼烫烫烫
编程语言与字符编码

← 手持两把锟斤拷,口中疾呼烫烫烫 编程语言与字符编码→

最近更新
01
吐槽一下《僵尸校园》
05-15
02
2025 年 4 月记
04-30
03
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式