1. MySQL數(shù)據(jù)庫字符集知識
1. 什么是字符集
字符編碼就是將人類使用的漢字(或其他語言)、英文字母、特殊符號等信息,通過預(yù)先設(shè)定的轉(zhuǎn)換規(guī)則,將其轉(zhuǎn)換為計算機可以識別的二進(jìn)制數(shù)字的一種編碼方式。
2. MySQL數(shù)據(jù)庫字符集
字符集其實就是一套文字符號及編碼,對應(yīng)的文字及編碼,可以將人類可以識別的內(nèi)容與計算機可以識別的信息進(jìn)行互相轉(zhuǎn)換。
假設(shè)有一個字母表使用了四個字母:A、B、a、b。我們?yōu)槊總€字母賦予一個數(shù)值:A=0,B=1,a=2,b=3.字母A是一個符號,數(shù)字0是A的編碼,這四個字母和它們的編碼組合在一起就可以成為一個字符集。
MySQL數(shù)據(jù)庫字符集不僅包括字符集(CHARACTER),還包括校對規(guī)則(COLLATION)。其中,校對規(guī)則的作用是定義比較字符串的方式。
假設(shè)希望比較兩個字符串的值:A和B。最簡單的方法是查找編碼:A為0,B為1。因為0小于1,所以可以說A小于B。可見,校對規(guī)則是一套規(guī)則,作用是對編碼進(jìn)行比較。
3. 常用字符集介紹與選擇建議
3.1 常用字符集介紹

3.2 MySQL如何選擇合適的字符集
- 如果存儲的是各種各樣的語言文字,則可以選擇UTF8,這是目前國內(nèi)應(yīng)用最為廣泛的字符集,沒有之一
- 如果只需要支持中文,并且數(shù)據(jù)量很大,此外,還包含了大量的運算,則可以選擇GBK,理論上其可以獲得更高的性能,但不推薦使用
- 對于新型的互聯(lián)網(wǎng)以及移動互聯(lián)網(wǎng)的混合業(yè)務(wù),推薦使用utf8mb4字符集替代UTF8字符集??傊?,如果沒有極特別的需求,請選擇UTF8或utf8mb4作為數(shù)據(jù)庫的字符集
- 如果使用開源程序,則可以根據(jù)上述說明進(jìn)行選擇,如果是公司開發(fā)人員自己開發(fā)產(chǎn)品,那么選擇權(quán)就在開發(fā)人員手里,DBA只能提供建議
3.3 查看MySQL數(shù)據(jù)庫字符集和校對規(guī)則
MySQL數(shù)據(jù)庫支持的字符集有很多種,通過以下命令可以查看當(dāng)前MySQL支持的字符集:
mysql> show character set;
+----------+-----------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+-----------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
---省略若干行...
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 |
| swe7 | 7bit Swedish | swe7_swedish_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
---省略若干行...
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 |
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| utf8 | UTF-8 Unicode | utf8_general_ci | 3 |
---省略若干行...
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci | 4 |
---省略若干行...
+----------+-----------------------------+---------------------+--------+
40 rows in set (0.04 sec)
2. MySQL數(shù)據(jù)庫字符集配置
設(shè)置MySQL的字符集需要考慮到很多個層次,大概分為以下7個級別:
- 操作系統(tǒng)級別
- 操作系統(tǒng)客戶端級別(SSH)
- MySQL實例級別
- 數(shù)據(jù)庫中的庫級別
- 表級別(含字段級別)
- MySQL客戶端級別(連接及返回結(jié)果)
- 程序代碼級別
1. Linux系統(tǒng)服務(wù)端字符集設(shè)置
很多人在使用MySQL時經(jīng)常會被中文亂碼所困擾,其中Linux系統(tǒng)和連接Linux系統(tǒng)客戶端的字符集設(shè)置可能就是問題之一,對此,要盡量將系統(tǒng)的字符集和系統(tǒng)中軟件的字符集進(jìn)行統(tǒng)一,設(shè)置和生效的方法具體如下:
[root@oldboy ~]# cat /etc/sysconfig/i18n ---配置到配置文件里可以永久生效
LANG="zh_CN.UTF-8" ---LANG為系統(tǒng)字符集環(huán)境變量,設(shè)置為中文UTF8
SYSFONT="latarcyrheb-sun16"
[root@oldboy ~]# source /etc/sysconfig/i18n ---使得修改立即生效
[root@oldboy ~]# echo $LANG
zh_CN.UTF-8
如果在Linux服務(wù)器里使用MySQL登錄到數(shù)據(jù)庫,則請注意系統(tǒng)字符集的使用
2. Linux系統(tǒng)客戶端字符集設(shè)置
常見的連接Linux系統(tǒng)的客戶端為SecureCRT、XShell,其中SecureCRT的配置如下圖所示:

XShell的配置如下圖所示:

方法1:前文在編譯安裝MySQL的時候就曾指定過如下的服務(wù)器端字符集
cmake .
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
方法2:如果編譯時沒指定字符集,或者指定了不合適的字符集,那么還可以在安裝后修改配置文件。
可按如下要求更改my.cnf參數(shù):
[mysqld]
character-set-server=utf8
方法3:還可以在啟動數(shù)據(jù)庫時,增加選項指定的字符集
mysqld --character-set-server=utf8 ---不推薦使用此方法
以上三種方法對數(shù)據(jù)庫的影響具體體現(xiàn)在輸出結(jié)果中有注釋的參數(shù)行上,具體如下:
mysql> show variables like 'character_set%';
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 ---MySQL中庫的字符集 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 ---MySQL服務(wù)器實例字符集 |
| character_set_system | utf8 |
| character_sets_dir | /application/mysql-5.6.41/share/charsets/ |
+--------------------------+-------------------------------------------+
8 rows in set (0.00 sec)
4. MySQL數(shù)據(jù)庫中的庫的字符集設(shè)置
在MySQL中,庫的字符集設(shè)置一般是在建庫的時候指定的,如果在建庫的時候未指定,則庫的字符集與MySQL數(shù)據(jù)庫實例的字符集一致??赏ㄟ^如下命令查看當(dāng)前實例的字符集:
mysql> show variables like 'character_set_database%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| character_set_database | utf8 |
+------------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'collation_database%';
+--------------------+-----------------+
| Variable_name | Value |
+--------------------+-----------------+
| collation_database | utf8_general_ci |
+--------------------+-----------------+
1 row in set (0.00 sec)
下面創(chuàng)建數(shù)據(jù)庫test,并查看建庫的字符集:
mysql> create database tingting;
Query OK, 1 row affected (0.00 sec)
mysql> show create database tingting\G
*************************** 1. row ***************************
Database: tingting
Create Database: CREATE DATABASE `tingting` /*!40100 DEFAULT CHARACTER SET utf8 */
1 row in set (0.00 sec)
在編譯MySQL時,若指定了正確的字符集或者修改配置文件調(diào)整過的服務(wù)器的字符集,那么,在以后建庫的時候就可以直接執(zhí)行簡化的命令“create database tingting;”。
也可以在建庫的時候指定字符集和校對規(guī)則來建庫:
create database oldboy DEFAULT CHARACTER SET UTF8 DEFAULT COLLATE = utf8_general_ci;
上面的語句為查看已建立的oldboy庫的語句,其中,“CHARACTER SET UTF8”即為數(shù)據(jù)庫字符集,而“utf8_general_ci”則為校對規(guī)則。
注意:采用二進(jìn)制方式安裝MySQL時,若沒有指定字符集,則此時字符集默認(rèn)為latin1,此時需要建立設(shè)置UTF8字符集的庫,即需要指定UTF8字符集建庫,否則就必須要提前修改配置文件,將服務(wù)器字符集調(diào)整為所需要的字符集。
5. MySQL數(shù)據(jù)庫表的字符集設(shè)置
默認(rèn)情況下,建表的字符集與庫的字符集應(yīng)一致,設(shè)置表字符集的命令如下:
mysql> use tingting
Database changed
mysql> create table test(id int(4));
Query OK, 0 rows affected (0.22 sec)
mysql> show create table test\G
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`id` int(4) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ---如果在建表時需要調(diào)整字符集,則必須制定字符集,則必須指定字符集
1 row in set (0.02 sec)
6. MySQL數(shù)據(jù)庫客戶端字符集設(shè)置
對MySQL數(shù)據(jù)庫客戶端字符集進(jìn)行設(shè)置,對于防止MySQL更新時,出現(xiàn)中文亂碼有極大的影響,設(shè)置方法如下。
方法1:臨時生效單條命令
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)
其中,“set names utf8”也可以用下面三個命令來代替
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
方法2:登錄數(shù)據(jù)庫時指定字符集
mysql --default-character-set=utf8;
方法3:通過修改my.cnf實現(xiàn)修改MySQL客戶端的字符集
[client]
default-character-set=utf8
以上幾種方法對數(shù)據(jù)庫的影響具體體現(xiàn)在輸出結(jié)果中有注釋的參數(shù)行上,具體如下:
mysql> show variables like 'character_set%';
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8 ---MySQL客戶端字符集 |
| character_set_connection | utf8 ---MySQL連接的字符集 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 ---MySQL返回結(jié)果的字符集 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /application/mysql-5.6.41/share/charsets/ |
+--------------------------+-------------------------------------------+
8 rows in set (0.00 sec)
7. 程序代碼字符集
很多開源軟件都會給出多種字符集的軟件代碼,例如,bbs軟件就是如此。Discuz! X3.2在集成和完善Discuz! 3.1的基礎(chǔ)上,針對社區(qū)移動端進(jìn)行了新的嘗試,比如,退出微信登錄、微社區(qū)等功能。它作為安全穩(wěn)定的程序可為站長提供更加可靠的保障。
3. 如何防止數(shù)據(jù)庫的中文顯示亂碼
管理員在配置MySQL數(shù)據(jù)庫字符集時,需要盡可能地確保前面提到的7大項字符集統(tǒng)一,查看數(shù)據(jù)庫字符集的基本方法如下:
mysql> show variables like 'character_set%';
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /application/mysql-5.6.41/share/charsets/ |
+--------------------------+-------------------------------------------+
8 rows in set (0.00 sec)
更改Linux系統(tǒng)字符集變量之后,可以查看MySQL中字符集的變化
徹底防止MySQL數(shù)據(jù)庫內(nèi)的數(shù)據(jù)中文亂碼方法
字符集的不一致是數(shù)據(jù)庫亂碼的罪魁禍?zhǔn)?,要想避免MySQL數(shù)據(jù)庫內(nèi)的數(shù)據(jù)庫中文亂碼方法,就要遵循前文所說的7大項字符集設(shè)置規(guī)則,即Linux系統(tǒng)服務(wù)端與Linux系統(tǒng)客戶端字符集、MySQL服務(wù)端數(shù)據(jù)庫實例與MySQL數(shù)據(jù)庫客戶端字符集、MySQL數(shù)據(jù)庫中的庫和表的字符集、程序代碼的字符集要一致。如果是利用文件還原數(shù)據(jù),還要注意文件的編碼問題。
以下是一個不按要求來操作,導(dǎo)致出現(xiàn)亂碼的范例:
mysql> set names gbk; ---修改MySQL客戶端字符集為GBK
Query OK, 0 rows affected (0.01 sec)
mysql> use tingting
Database changed
mysql> create table t1(id int(4),name varchar(16));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into t1 values(1,'老男');
Query OK, 1 row affected (0.03 sec)
mysql> select * from t1;
+------+--------+
| id | name |
+------+--------+
| 1 | 老男 |
+------+--------+
1 row in set (0.00 sec)
mysql> set names utf8; ---修改MySQL客戶端字符集為UTF8
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1;
+------+-----------+
| id | name |
+------+-----------+
| 1 | 鑰佺敺 | ---發(fā)現(xiàn)數(shù)據(jù)亂碼了,這就是客戶端字符集和服務(wù)端不一致時插入數(shù)據(jù)而導(dǎo)致的亂碼問題
+------+-----------+
1 row in set (0.00 sec)
4. 如何更改MySQL數(shù)據(jù)庫庫表的字符集
1. 更改庫的字符集
管理員可以使用alter命令對數(shù)據(jù)庫的字符集進(jìn)行更改:
mysql> show create database oldboy\G
*************************** 1. row ***************************
Database: oldboy
Create Database: CREATE DATABASE `oldboy` /*!40100 DEFAULT CHARACTER SET utf8 */
1 row in set (0.00 sec)
mysql> alter database oldboy CHARACTER SET latin1 COLLATE = latin1_swedish_ci;
Query OK, 1 row affected (0.02 sec)
mysql> show create database oldboy\G
*************************** 1. row ***************************
Database: oldboy
Create Database: CREATE DATABASE `oldboy` /*!40100 DEFAULT CHARACTER SET latin1 */
1 row in set (0.00 sec)
mysql> alter database oldboy CHARACTER SET utf8 collate utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> show create database oldboy\G
*************************** 1. row ***************************
Database: oldboy
Create Database: CREATE DATABASE `oldboy` /*!40100 DEFAULT CHARACTER SET utf8 */
1 row in set (0.00 sec)
2. 更改表的字符集
管理員也可以使用alter命令對數(shù)據(jù)庫的表的字符集進(jìn)行更改:
mysql> use tingting
Database changed
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(4) DEFAULT NULL,
`name` varchar(16) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> alter table t1 CHARACTER SET latin1;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(4) DEFAULT NULL,
`name` varchar(16) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
上面僅僅是修改字符集的基本操作,若是對于已經(jīng)上線的數(shù)據(jù)庫,并且已經(jīng)包含了很多數(shù)據(jù),就無法使用這個方法了,使用“alter database dbname character set *”修改庫的字符集,或者使用“alter table tablename character set *”更改表的字符集,只對新創(chuàng)建的表或者更新的數(shù)據(jù)生效。
3. 生產(chǎn)環(huán)境更改數(shù)據(jù)庫(含數(shù)據(jù))字符集的方法
對于已經(jīng)包含了數(shù)據(jù)的庫表,若要對字符集進(jìn)行調(diào)整,就需要將數(shù)據(jù)先導(dǎo)出,然后更改數(shù)據(jù)庫環(huán)境,更改建庫環(huán)境,更改建庫和表的字符集之后,重新導(dǎo)入數(shù)據(jù),這樣才能實現(xiàn)相應(yīng)的調(diào)整。整個過程具體如下:
1)確保數(shù)據(jù)庫不要更新,然后導(dǎo)出所有數(shù)據(jù)為SQL的文件
2)針對導(dǎo)出的數(shù)據(jù)進(jìn)行字符集替換(替換表和庫),例如把GBK改為UTF8
3)修改my.cnf配置文件,更改MySQL客戶端及服務(wù)端的字符集,重啟生效
4)導(dǎo)入更改過新字符集的庫表的數(shù)據(jù),包括表結(jié)構(gòu)語句,然后提供服務(wù)
5)將操作系統(tǒng),SSH客戶端,以及程序更改為對應(yīng)的新字符集
另外,更改字符集時,要將小的字符集集合更改為大的字符集集合,不然可能會丟失數(shù)據(jù)。