# 亂碼??是怎么出現的
先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
# 對已有錯誤字符集的數據更改為正確的字符集