Bootstrap

【Mysql】Mysql 字符集与底层原理


前言

一、查看与修改 Mysql 默认的字符集

1、查看 Mysql 默认的字符集

-- 查看 mysql 默认字符集
SHOW VARIABLES LIKE 'character_%';
-- 查看 mysql 默认字符排序
SHOW VARIABLES LIKE 'collation_%';

返回的结果为:

Variable_nameValue
character_set_clientutf8mb4
character_set_connectionutf8mb4
character_set_databaseutf8mb4
character_set_filesystembinary
character_set_resultsutf8mb4
character_set_serverutf8mb4
character_set_systemutf8mb3
character_sets_dirD:\java_web\java_environment\Mysql\MySQL Server 8.0\share\charsets|

Variable_nameValue
collation_connectionutf8mb4_0900_ai_ci
collation_databaseutf8mb4_0900_ai_ci
collation_serverutf8mb4_0900_ai_ci

当 character_set_database 与 character_set_server 为 utf8mb4 时,新建数据库与表的时候默认的字符编码集就是 utf8mb4。
当 collation_database 与 collation_server 为 utf8mb4_0900_ai_ci 时,新建表的时候默认的字符比较规则就是 utf8mb4_0900_ai_ci。
我们可以测试一下:

-- 新建一个数据库
CREATE DATABASE test_database;
-- 查看数据库信息
SHOW CREATE DATABASE test_database;
-- 使用新建数据库
USE test_database;
-- 新建一个表
CREATE TABLE test_table(id INT, name VARCHAR(10));
-- 查看表信息
SHOW CREATE TABLE test_table;

运行 SHOW CREATE DATABASE test_database; 的结果为

DatabaseCreate Database
test_databaseCREATE DATABASE test_database /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci / /!80016 DEFAULT ENCRYPTION=‘N’ */

运行 SHOW CREATE TABLE test_table; 结果为

TableCreate Table
test_tableCREATE TABLE test_table (
id int DEFAULT NULL,
name varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

2、修改 Mysql 默认字符集

windows 环境

修改数据库 my.ini 文件

在 [mysql] 下修改
default-character-set=utf8
在 [mysqld] 下修改
character-set-server=utf8
collation-server=utf8_general_ci

重启服务,服务名每台电脑不一样,Mysql 8.0 版本默认是 MYSQL80

net stop MYSQL80
net start MYSQL80

Linux 环境

修改数据库 my.cnf 文件,一般在 /etc/my.cnf。

在 [mysql] 下修改
default-character-set=utf8
在 [mysqld] 下修改
character-set-server=utf8
collation-server=utf8_general_ci

重启服务

systemctl restart mysqld.service

二、Mysql 数据库字符集级别

Mysql 有四个字符集与比较级别

  1. 服务器级别
  2. 数据库级别
  3. 表级别
  4. 列级别

我们再看下数据库字符集的参数:

  • character_set_client:服务器解码请求时使用的字符集
  • character_set_connection:服务器处理请求时会把请求字符串从 character_set_client 转为该字符集
  • character_set_database:当前数据库的字符集
  • character_set_results:服务器向客户端返回时使用的字符集
  • character_set_server:服务器级别的字符集

其中 character_set_client、character_set_connection、character_set_results 这三个是客户端每次链接进来设置的,与服务端没关系。所以每一个客户端看到的是自己链接数据库所配置的字符集,所以看到的也并不相同。如果想要修改可以直接使用 sql 进行修改,如:SET character_set_connection = 'utf8';
character_set_database 是当前所在库的字符集,切换不同的数据库可以看到对应数据库的字符集。
character_set_server 是服务器配置的字符集,需要修改的话就必须在 Mysql 的配置文件中修改,在 Mysql 8.0 版本以上默认是 utfmb4,在 8.0 版本以下默认是 latin1。
在这四个级别中
新建数据库的时候如果不指定字符集与字符比较方式就会默认以服务器级别为准;
新建表的时候如果不指定字符集与字符比较方式时就会默认以数据库级别为准;
新建字段的时候如果不指定字符集与字符比较方式时就会默认以表级别为准。


三、字符集比较规则

1、utf8 与 utf8mb4 的区别

utf-8 字符集需要 1 ~ 4 个字节表示一个字符,我们常用的一些字符使用 1 ~ 3 个字节就通常就可以表示。于是 Mysql 设计的时候就将 utf8 定义了两套字符集:一套是能满足平时大多数情况且占内存较少的字符集 utf8mb3,字符只占 1 ~ 3 个字节;一套是能满足所有情况但是相对比较占用内存的字符集 utf8mb4,字符需占用 1 ~ 4 个字节。

  • utf8 与可以叫 utf8mb3,仅是 utf-8 的一部分,表示一个字符需要 1 ~ 3 个字节。
  • utf8mb4 表示一个字符需要 1 ~ 4 个字节。可以存储一些 emoji 表情。

2、查看 Mysql 中的字符集

SHOW CHARSET;

返回结果:

CharsetDescriptionDefault collationMaxien
armscii8ARMSCII-8 Armenianarmscii8_general_ci1
asciiUS ASCIIascii_general_ci1
big5Big5 Traditional Chinesebig5_chinese_ci2
binaryBinary pseudo charsetbinary1
cp1250Windows Central Europeancp1250_general_ci1
cp1251Windows Cyrilliccp1251_general_ci1
cp1256Windows Arabiccp1256_general_ci1
cp1257Windows Balticcp1257_general_ci1
cp850DOS West Europeancp850_general_ci1
cp852DOS Central Europeancp852_general_ci1
cp866DOS Russiancp866_general_ci1
cp932SJIS for Windows Japanesecp932_japanese_ci2
dec8DEC West Europeandec8_swedish_ci1
eucjpmsUJIS for Windows Japaneseeucjpms_japanese_ci3
euckrEUC-KR Koreaneuckr_korean_ci2
gb18030China National Standard GB18030gb18030_chinese_ci4
gb2312GB2312 Simplified Chinesegb2312_chinese_ci2
gbkGBK Simplified Chinesegbk_chinese_ci2
geostd8GEOSTD8 Georgiangeostd8_general_ci1
greekISO 8859-7 Greekgreek_general_ci1
hebrewISO 8859-8 Hebrewhebrew_general_ci1
hp8HP West Europeanhp8_english_ci1
keybcs2DOS Kamenicky Czech-Slovakkeybcs2_general_ci1
koi8rKOI8-R Relcom Russiankoi8r_general_ci1
koi8uKOI8-U Ukrainiankoi8u_general_ci1
latin1cp1252 West Europeanlatin1_swedish_ci1
latin2ISO 8859-2 Central Europeanlatin2_general_ci1
latin5ISO 8859-9 Turkishlatin5_turkish_ci1
latin7ISO 8859-13 Balticlatin7_general_ci1
macceMac Central Europeanmacce_general_ci1
macromanMac West Europeanmacroman_general_ci1
sjisShift-JIS Japanesesjis_japanese_ci2
swe77bit Swedishswe7_swedish_ci1
tis620TIS620 Thaitis620_thai_ci1
ucs2UCS-2 Unicodeucs2_general_ci2
ujisEUC-JP Japaneseujis_japanese_ci3
utf16UTF-16 Unicodeutf16_general_ci4
utf16leUTF-16LE Unicodeutf16le_general_ci4
utf32UTF-32 Unicodeutf32_general_ci4
utf8mb3UTF-8 Unicodeutf8mb3_general_ci3
utf8mb4UTF-8 Unicodeutf8mb4_0900_ai_ci4

我们常用的有:专门描述汉字的字符集 gb2312、gbk;国际通用字符集:utf8mb3、utf8mb4。

3、字符比较规则

后缀英文释义描述
_aiaccent_insensitive不区分重音
_asaccent_sensitive区分重音
_cicase_insensitive不区分大小写
_cscase_sensitive区分大小写
_binbinary以二进制方式比较

查看字符集比较规则

SHOW COLLATION LIKE 'utf8mb4%';

结果如下:

CollationCharsetIdDefaultCompiledSortlenPad_attribute
utf8mb4_0900_ai_ciutf8mb4255YesYes0NO PAD
utf8mb4_0900_as_ciutf8mb4305Yes0NO PAD
utf8mb4_0900_as_csutf8mb4278Yes0NO PAD
utf8mb4_0900_binutf8mb4309Yes1NO PAD
utf8mb4_bg_0900_ai_ciutf8mb4318Yes0NO PAD
utf8mb4_bg_0900_as_csutf8mb4319Yes0NO PAD
utf8mb4_binutf8mb446Yes1PAD SPACE
utf8mb4_bs_0900_ai_ciutf8mb4316Yes0NO PAD
utf8mb4_bs_0900_as_csutf8mb4317Yes0NO PAD
utf8mb4_croatian_ciutf8mb4245Yes8PAD SPACE
utf8mb4_cs_0900_ai_ciutf8mb4266Yes0NO PAD
utf8mb4_cs_0900_as_csutf8mb4289Yes0NO PAD
utf8mb4_czech_ciutf8mb4234Yes8PAD SPACE
utf8mb4_danish_ciutf8mb4235Yes8PAD SPACE
utf8mb4_da_0900_ai_ciutf8mb4267Yes0NO PAD
utf8mb4_da_0900_as_csutf8mb4290Yes0NO PAD
utf8mb4_de_pb_0900_ai_ciutf8mb4256Yes0NO PAD
utf8mb4_de_pb_0900_as_csutf8mb4279Yes0NO PAD
utf8mb4_eo_0900_ai_ciutf8mb4273Yes0NO PAD
utf8mb4_eo_0900_as_csutf8mb4296Yes0NO PAD
utf8mb4_esperanto_ciutf8mb4241Yes8PAD SPACE
utf8mb4_estonian_ciutf8mb4230Yes8PAD SPACE
utf8mb4_es_0900_ai_ciutf8mb4263Yes0NO PAD
utf8mb4_es_0900_as_csutf8mb4286Yes0NO PAD
utf8mb4_es_trad_0900_ai_ciutf8mb4270Yes0NO PAD
utf8mb4_es_trad_0900_as_csutf8mb4293Yes0NO PAD
utf8mb4_et_0900_ai_ciutf8mb4262Yes0NO PAD
utf8mb4_et_0900_as_csutf8mb4285Yes0NO PAD
utf8mb4_general_ciutf8mb445Yes1PAD SPACE
utf8mb4_german2_ciutf8mb4244Yes8PAD SPACE
utf8mb4_gl_0900_ai_ciutf8mb4320Yes0NO PAD
utf8mb4_gl_0900_as_csutf8mb4321Yes0NO PAD
utf8mb4_hr_0900_ai_ciutf8mb4275Yes0NO PAD
utf8mb4_hr_0900_as_csutf8mb4298Yes0NO PAD
utf8mb4_hungarian_ciutf8mb4242Yes8PAD SPACE
utf8mb4_hu_0900_ai_ciutf8mb4274Yes0NO PAD
utf8mb4_hu_0900_as_csutf8mb4297Yes0NO PAD
utf8mb4_icelandic_ciutf8mb4225Yes8PAD SPACE
utf8mb4_is_0900_ai_ciutf8mb4257Yes0NO PAD
utf8mb4_is_0900_as_csutf8mb4280Yes0NO PAD
utf8mb4_ja_0900_as_csutf8mb4303Yes0NO PAD
utf8mb4_ja_0900_as_cs_ksutf8mb4304Yes24NO PAD
utf8mb4_latvian_ciutf8mb4226Yes8PAD SPACE
utf8mb4_la_0900_ai_ciutf8mb4271Yes0NO PAD
utf8mb4_la_0900_as_csutf8mb4294Yes0NO PAD
utf8mb4_lithuanian_ciutf8mb4236Yes8PAD SPACE
utf8mb4_lt_0900_ai_ciutf8mb4268Yes0NO PAD
utf8mb4_lt_0900_as_csutf8mb4291Yes0NO PAD
utf8mb4_lv_0900_ai_ciutf8mb4258Yes0NO PAD
utf8mb4_lv_0900_as_csutf8mb4281Yes0NO PAD
utf8mb4_mn_cyrl_0900_ai_ciutf8mb4322Yes0NO PAD
utf8mb4_mn_cyrl_0900_as_csutf8mb4323Yes0NO PAD
utf8mb4_nb_0900_ai_ciutf8mb4310Yes0NO PAD
utf8mb4_nb_0900_as_csutf8mb4311Yes0NO PAD
utf8mb4_nn_0900_ai_ciutf8mb4312Yes0NO PAD
utf8mb4_nn_0900_as_csutf8mb4313Yes0NO PAD
utf8mb4_persian_ciutf8mb4240Yes8PAD SPACE
utf8mb4_pl_0900_ai_ciutf8mb4261Yes0NO PAD
utf8mb4_pl_0900_as_csutf8mb4284Yes0NO PAD
utf8mb4_polish_ciutf8mb4229Yes8PAD SPACE
utf8mb4_romanian_ciutf8mb4227Yes8PAD SPACE
utf8mb4_roman_ciutf8mb4239Yes8PAD SPACE
utf8mb4_ro_0900_ai_ciutf8mb4259Yes0NO PAD
utf8mb4_ro_0900_as_csutf8mb4282Yes0NO PAD
utf8mb4_ru_0900_ai_ciutf8mb4306Yes0NO PAD
utf8mb4_ru_0900_as_csutf8mb4307Yes0NO PAD
utf8mb4_sinhala_ciutf8mb4243Yes8PAD SPACE
utf8mb4_sk_0900_ai_ciutf8mb4269Yes0NO PAD
utf8mb4_sk_0900_as_csutf8mb4292Yes0NO PAD
utf8mb4_slovak_ciutf8mb4237Yes8PAD SPACE
utf8mb4_slovenian_ciutf8mb4228Yes8PAD SPACE
utf8mb4_sl_0900_ai_ciutf8mb4260Yes0NO PAD
utf8mb4_sl_0900_as_csutf8mb4283Yes0NO PAD
utf8mb4_spanish2_ciutf8mb4238Yes8PAD SPACE
utf8mb4_spanish_ciutf8mb4231Yes8PAD SPACE
utf8mb4_sr_latn_0900_ai_ciutf8mb4314Yes0NO PAD
utf8mb4_sr_latn_0900_as_csutf8mb4315Yes0NO PAD
utf8mb4_sv_0900_ai_ciutf8mb4264Yes0NO PAD
utf8mb4_sv_0900_as_csutf8mb4287Yes0NO PAD
utf8mb4_swedish_ciutf8mb4232Yes8PAD SPACE
utf8mb4_tr_0900_ai_ciutf8mb4265Yes0NO PAD
utf8mb4_tr_0900_as_csutf8mb4288Yes0NO PAD
utf8mb4_turkish_ciutf8mb4233Yes8PAD SPACE
utf8mb4_unicode_520_ciutf8mb4246Yes8PAD SPACE
utf8mb4_unicode_ciutf8mb4224Yes8PAD SPACE
utf8mb4_vietnamese_ciutf8mb4247Yes8PAD SPACE
utf8mb4_vi_0900_ai_ciutf8mb4277Yes0NO PAD
utf8mb4_vi_0900_as_csutf8mb4300Yes0NO PAD
utf8mb4_zh_0900_as_csutf8mb4308Yes0NO PAD

查看服务级别的字符集与比较规则

SHOW VARIABLES LIKE '%_server';

结果如下

Variable_nameValue
character_set_serverutf8mb4
collation_serverutf8mb4_0900_ai_ci
innodb_dedicated_serverOFF

修改具体数据库的字符集和比较规则

ALTER DATABASE test2 CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';

查看:

SHOW CREATE DATABASE test2;

结果如下:

DatabaseCreate Database
test2CREATE DATABASE test2 /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci / /!80016 DEFAULT ENCRYPTION=‘N’ */

utf8mb4_general_ci 和 utf8mb4_unicode_ci 对比

utf8mb4_general_ci 和 utf8mb4_unicode_ci 都是比较常用的两种字符比较方式。

  • utf8mb4_general_ci 校对速度快,准确度稍差
  • utf8mb4_unicode_ci 准确度高,校对速度较慢

一般情况使用 utf8mb4_general_ci 就足够用了,但是在有德语、法语或俄语的时候一定要使用 utf8mb4_unicode_ci。

查看表的状态与字符比较规则

SHOW TABLE STATUS FROM test2 LIKE 'user';

总结

总体来说 Mysql 的字符集有 4 个级别服务级别、数据库级别、表级别、列级别。确定某条数据的以最小级别为主,如表的字符集为 utf8,而字段的字符集为 gbk,则该字段以 gbk 进行编码。在创建数据库、表、列的时候如果不确定其字符集,则以上一个字符集级别为准。
如果想要修改服务级别的字符集和字符排序方式,windows 修改 my.ini 文件,linux 修改 my.cnf 文件。修改后对原来的数据库与表没有影响,如果想要修改之前的数据库与表的字符集或字符排序方式则仍需要使用 alter 语句进行修改。
在 Mysql 中 utf8 被分为 utf8mb3 与 utf8mb4 两种,utf8mb3 可以满足多部份场景,对 emoj 表情不识别,utf8mb4 满足所有场景,缺点是比较占用内存。
utf8 的字符集排序方式常用的有两个 general_ci 和 unicode_ci,general_ci 速度比较快,但是德语、法语、俄语的准确度有影响,需要使用 unicode_ci。

;