MySQL亂碼的原因和設(shè)置UTF8數(shù)據(jù)格式

MySQL使用時帖努,有一件很痛苦的事情肯定是結(jié)果亂碼观话。將編碼格式都設(shè)置為UTF8可以解決這個問題,我們今天來說下為什么要這么設(shè)置宇姚,以及怎么設(shè)置。

MySQL字符格式

字符集

在編程語言中夫凸,我們?yōu)榱朔乐怪形膩y碼浑劳,會使用unicode對中文字符做處理,而為了降低網(wǎng)絡帶寬和節(jié)省存儲空間夭拌,我們使用UTF8進行編碼魔熏。對這兩者有什么不同不夠了解的同學,可以參考Unicode字符集和UTF8編碼編碼的前世今生這篇文章鸽扁。

同樣在MySQL中道逗,我們也會有這樣的處理,我們可以查看當前數(shù)據(jù)庫設(shè)置的編碼方式(字符集):

````mysql> show variables like '%char%';

+--------------------------+----------------------------------+

| Variable_name | Value |

+--------------------------+----------------------------------+

| character_set_client | latin1 |

| character_set_connection | latin1 |

| character_set_database | latin1 |

| character_set_filesystem | binary |

| character_set_results | latin1 |

| character_set_server | latin1 |

| character_set_system | utf8 |

| character_sets_dir | /usr/local/mysql/share/charsets/ |

+--------------------------+----------------------------------+

8 rows in set (0.00 sec)````

表中就是當前設(shè)置的字符集献烦,先看不用關(guān)注的幾個值:

character_set_filesystem | binary:文件系統(tǒng)上的存儲格式滓窍,默認為binary(二進制)

character_set_system | utf8:系統(tǒng)的存儲格式,默認為utf8

character_sets_dir | /usr/local/mysql/share/charsets/:可以使用的字符集的文件路徑

剩下的幾個就是日常影響讀寫亂碼的參數(shù)了:

- character_set_client:客戶端請求數(shù)據(jù)的字符集

- character_set_connection:從客戶端接收到數(shù)據(jù)巩那,然后傳輸?shù)淖址?/p>

- character_set_database:默認數(shù)據(jù)庫的字符集吏夯;如果沒有默認數(shù)據(jù)庫此蜈,使用character_set_server字段

- character_set_results:結(jié)果集的字符集

- character_set_server:數(shù)據(jù)庫服務器的默認字符集

字符集的轉(zhuǎn)換流程分為3步:

客戶端請求數(shù)據(jù)庫數(shù)據(jù),發(fā)送的數(shù)據(jù)使用character_set_client字符集

MySQL實例收到客戶端發(fā)送的數(shù)據(jù)后噪生,將其轉(zhuǎn)換為character_set_connection字符集

進行內(nèi)部操作時裆赵,將數(shù)據(jù)字符集轉(zhuǎn)換為內(nèi)部操作字符集:

使用每個數(shù)據(jù)字段的character set設(shè)定值

若不存在,使用對應數(shù)據(jù)表的default character set設(shè)定值

若不存在跺嗽,使用對應數(shù)據(jù)庫的default character set設(shè)定值

若不存在战授,使用character_set_server設(shè)定值

將操作結(jié)果值從內(nèi)部操作字符集轉(zhuǎn)換為character_set_results

字符序

說字符序之前,我們需要了解一點基礎(chǔ)知識:

字符(Character)是指人類語言中最小的表義符號桨嫁。例如’A’植兰、’B’等;

給定一系列字符璃吧,對每個字符賦予一個數(shù)值楣导,用數(shù)值來代表對應的字符,這一數(shù)值就是字符的編碼(Encoding)畜挨。例如筒繁,我們給字符’A’賦予數(shù)值0,給字符’B’賦予數(shù)值1巴元,則0就是字符’A’的編碼毡咏;

給定一系列字符并賦予對應的編碼后,所有這些字符和編碼對組成的集合就是字符集(Character Set)逮刨。例如血当,給定字符列表為{‘A’,’B’}時,{‘A’=>0, ‘B’=>1}就是一個字符集禀忆;

字符序(Collation)是指在同一字符集內(nèi)字符之間的比較規(guī)則;

確定字符序后落恼,才能在一個字符集上定義什么是等價的字符箩退,以及字符之間的大小關(guān)系;

每個字符序唯一對應一種字符集佳谦,但一個字符集可以對應多種字符序戴涝,其中有一個是默認字符序(Default Collation)钻蔑;

MySQL中的字符序名稱遵從命名慣例:以字符序?qū)淖址Q開頭;以_ci(表示大小寫不敏感咪笑,case insensitive)、_cs(表示大小寫敏感窗怒,case sensitive)或_bin(表示按編碼值比較映跟,binary)結(jié)尾蓄拣。例如:在字符序“utf8_general_ci”下努隙,字符“a”和“A”是等價的;

因此字符序不同于字符集荸镊,用于數(shù)據(jù)庫字段的相等或大小比較咽斧。我們查看MySQL實例設(shè)置的字符序:

````mysql> show variables like 'collation%';

+----------------------+-------------------+

| Variable_name | Value |

+----------------------+-------------------+

| collation_connection | latin1_swedish_ci |

| collation_database | latin1_swedish_ci |

| collation_server | latin1_swedish_ci |

+----------------------+-------------------+

3 rows in set (0.00 sec)````

跟utf8對應的常用字符序是:utf8_unicode_ci/utf8_general_ci和utf8_bin等,那么他們的區(qū)別是什么呢躬存?

_bin是用二進制存儲并比較,區(qū)別大小寫优构,存儲二進制內(nèi)容時使用

utf8_general_ci:校對速度快,但準確度稍差拧额,使用中英文時使用

utf8_unicode_ci:準確度高彪腔,但校對速度稍慢,使用德法俄等外語時使用

詳細的區(qū)別可以參考 Mysql中的排序規(guī)則utf8_unicode_ci德挣、utf8_general_ci的區(qū)別總結(jié)。

修改字符集和字符序

如果在MySQL連接時格嗅,出現(xiàn)了亂碼的問題,那么基本可以確定是各個字符集/序設(shè)置不統(tǒng)一的原因玄柏。MySQL默認的latin1格式不支持中文贴铜,由于我們在中國,所以選擇對中文和各語言支持都非常完善的utf8格式绍坝。所以,我們需要將需要關(guān)注的字符集和字符序都修改為utf8格式椎咧。

你也可以選擇utf8mb4格式把介,這個格式支持保存emoji表情竹宋。

我們需要修改Mysql的配置文件地技,查看配置文件的位置有兩種方式:

````1. $ mysql --help | grep 'my.cnf'

/etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf

2. ps aux | grep mysql````

在(1)中,/etc/my.cnf, /etc/mysql/my.cnf, ~/.my.cnf 這些就是mysql默認會搜尋my.cnf的目錄莫矗,優(yōu)先級依次升高∪洌可以在各個配置文件里都使用long_query_time 來測試一下妹懒。

然后,我們修改或新增下面的配置項:

# 下面注釋的幾行可以不設(shè)置眨唬,但如果你的沒有生效,也可以試試看

````[mysqld]

character_set_server=utf8

collation-server=utf8_general_ci

skip-character-set-client-handshake

#init_connect='SET NAMES utf8'

#[client]

#default-character-set=utf8````

這三行配置就可以解決問題瓦宜,最關(guān)鍵的是最后一行岭妖,參考mysql文檔,使用該參數(shù)會忽略客戶端傳遞的字符集信息假夺,而直接使用服務端的設(shè)定斋攀;再加上我們設(shè)定服務端的字符集和字符序均為utf8,這樣就保證了字符格式的統(tǒng)一蜻韭,解決亂碼的問題柿扣。

重啟mysql服務,如果提示找不到服務俯画,請參考用service命令管理mysql啟停:

````$ service mysqld restart

Shutting down MySQL.. [ OK ]

Starting MySQL. [ OK ]

連接到mysql司草,查看當前編碼:

mysql> show variables like '%char%';

+--------------------------+----------------------------------+

| 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 | /usr/local/mysql/share/charsets/ |

+--------------------------+----------------------------------+

8 rows in set (0.01 sec)

mysql> show variables like 'collation%';

+----------------------+-----------------+

| Variable_name | Value |

+----------------------+-----------------+

| collation_connection | utf8_general_ci |

| collation_database | utf8_general_ci |

| collation_server | utf8_general_ci |

+----------------------+-----------------+

3 rows in set (0.01 sec)````

可以看到一切都符合預期,請求和存儲的數(shù)據(jù)也不再是亂碼了猜憎。

遇到的問題

unknown variable 'default-character-set=utf8'

參考官方文檔,該參數(shù)自5.5.3版本廢棄截亦,改為了character-set-server柬讨,改為這個參數(shù)即可。

但這個是在[mysqld]下的配置踩官,在[client]下的配置依然使用default-character-set參數(shù)。


獲取以上Java高級架構(gòu)最新視頻颖系,歡迎

加入Java進階架構(gòu)交流群:142019080蛋逾。直接點擊鏈接加群。

https://jq.qq.com/?_wv=1027&k=5lXBNZ7

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偷拔,一起剝皮案震驚了整個濱河市亏钩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛤签,老刑警劉巖栅哀,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異戳晌,居然都是意外死亡痴柔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門豪嚎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侈询,你說我怎么就攤上這事∑镁” “怎么了啦租?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長焊刹。 經(jīng)常有香客問我恳蹲,道長,這世上最難降的妖魔是什么嘉蕾? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任错忱,我火速辦了婚禮,結(jié)果婚禮上以清,老公的妹妹穿的比我還像新娘。我一直安慰自己眉孩,他們只是感情好勒葱,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著死遭,像睡著了一般涩维。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓦阐,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天睡蟋,我揣著相機與錄音,去河邊找鬼戳杀。 笑死,一個胖子當著我的面吹牛隔缀,可吹牛的內(nèi)容都是我干的傍菇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼丢习,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了揽思?” 一聲冷哼從身側(cè)響起见擦,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎儡湾,沒想到半個月后执俩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡尝丐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年衡奥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片失息。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖邻梆,靈堂內(nèi)的尸體忽然破棺而出绎秒,到底是詐尸還是另有隱情浦妄,我是刑警寧澤见芹,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏故黑。R本人自食惡果不足惜庭砍,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一怠缸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧揭北,春花似錦、人聲如沸恨樟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呆奕。三九已至,卻和暖如春绳泉,著一層夾襖步出監(jiān)牢的瞬間姆泻,已是汗流浹背冒嫡。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工四苇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛔琅。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓罗售,卻偏偏與公主長得像钩述,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子牙勘,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容