🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 乱码??是怎么出现的 先YUM安装数据库(此时字符集默认拉丁1) 正常建库: >create database xr; 正常建表: >use xr; 并且 ``` create table stu( snum int, sname varchar(10) ); ``` 正常插入数据: ``` insert into stu values (1,'zhangsan'), (2,'lisi'), (3,'wangwu'); (4,'我是'); ``` 显示数据: >select * from stu; 发现乱码 # 怎么不乱码? >set names latin1; 然后插入字符发现不乱码了 **不管是文件还是命令行,不管是查询还是插入,都在之前输了这个语句** 或者在打开数据库时: >mysql -uroot -p123456 --default-character-set=utf8 但是已经出现问题的数据库就没办法了。 ## 如何保证不乱码的最终策略 在配置文件中my.cnf中 在\[client\]和\[mysqld\]中配置相同的字符集 **客户端,服务端,库,表,前端程序,Linux系统,Xshell的设置,XFTP传的各种文件的字符集全部统一,就不会乱码,而且前面的情况缺一不可** # 为什么我的WordPress不乱码 ## 前提 在数据库中 >show variables like "%character%"; 我的Mariadb的数据库编码是 | character_set_client客户端发送过来文字的字符集 utf8 | character_set_connection连接时的编码格式 utf8 | character_set_database数据库存储的编码格式 latin1 | character_set_filesystem文件存储编码格式 binary | character_set_results发送给客户端的结果所使用的字符集 utf8 | character_set_server数据库服务器端的编码格式 latin1 | character_set_system据库所在系统的编码格式(指Linux系统或Windows系统) utf8 | character_sets_dir数据库可用的字符集/usr/share/mysql/charsets/ 在服务端的字符集: character_set_server 我的是latin1 character_set_database 我的是latin1 在客户端的字符集: character_set_client 我的是utf8 character_set_results 我的是utf8 用于客户端和服务器连接的字符集: character_set_connection 我的是utf8 而且WordPress的文本也是UTF8的,大多数CMS都是用UTF8的,很多软件传输时用的也都是utf8 ## 总结 默认的客户端编码、默认的连接编码是utf8,这也就是说,WordPress传递给MySQL的文本都是用utf8编码的,而且连接时的编码也是utf8的,所以没有任何问题。 但是在服务端存储数据时是以latin1存储,一个汉字会从3Byte变成6Byte,存储效率绝对会变低,而且转化是需要CPU,性能也做了无用功。白白浪费电。 ## 其他情况 如果有人的数据库编码为 character_set_server:utf8 character_set_database:utf8 且 character_set_client:latin1 character_set_results latin1 character_set_connection:latin1 可见,默认的客户端编码、默认的连接编码是latin1,这也就是说,虽然实际上WordPress传递给数据库服务端的文本都是用utf8编码的,但是由于上述系统变量设置不当,这些utf8编码的文本被当作是latin1编码的文本传输,并且由于数据库本身是utf8,因此把这些"latin1文本"(实际上是utf8文本)又转换成了utf8。这样,可想而知,在数据库中查看这些数据绝对是乱码。 那么为什么这些乱码在WordPress显示时没问题呢?这是因为,数据库服务器在取出数据交给WordPress时,把这些数据从乱码转换回latin1,然后wordpress将这些latin1又当作了utf8,错错得对,显示的没有任何问题。 # 永久修改默认字符集 ## 思路 服务器(数据)端的字符集和collation,可以分成四级逐层指定——server, database, table, column。当MySQL存取位于某一列(column)的数据时,如果column的字符集和collation没有指定,就会向上追溯table的;如果table也没有指定字符集和collation,就以database的字符集和collation作为默认值;如果database仍旧没有指定,那么就以服务器的字符集和collation作为默认值。 那么server的字符集和collation的默认值又是从哪里来的呢?答案是,配置文件(my.ini)和mysqld(或者mysqld-nt)的命令行参数中都可以指定。如果不幸的,你根本没有在my.ini或者命令行中指定,那么MySQL就会使用编译MySQL时指定的默认字符集——latin1。 但是,需要注意的是,如果安装数据库时选择了多语言支持(Windows),安装程序会自动在配置文件中设置utf8 ## 注意 Mariadb和MySQL数据库的utf8是3个Byte的,而且无法使用emoji图片,**也可能**无法存储中文的某些标点和出现各种各样的BUG。 所以为了不出错和兼容性,不管有没有使用场景都需要改为utf8mb4!!! ## 做法 先修改服务端字符为utf8mb4 >show variables like "%character%"; character_set_server:latin1 character_set_database:latin1 >show variables like "%collation%"; collation_database:latin1_swedish_ci collation_server:latin1_swedish_ci >vim /etc/my.cnf.d/server.cnf 在[mysqld]标签下添加或修改为下面内容 character-set-client-handshake = FALSE character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect = 'SET NAMES utf8mb4' 再修改客户端字符为utf8mb4 >vim /etc/my.cnf.d/mysql-clients.cnf 在[mysql]标签下添加或修改为下面内容 default-character-set = utf8mb4 # 对已有错误字符集的数据更改为正确的字符集