字符集GBK升级UTF8
? ? ?在生產環境中,數據庫字符集因為各種原因需要升級,比如為了支持漢字,從latin1字符集升級到GBK,后面為了支持多個語言文字,需要將GBK升級到UTF8等。遷移過程網上有很多,我今天主要想講下字符集轉換后,可能對業務產生的影響,我以GBK轉換到UTF8為例說明。主要有兩點:
這篇文章主要為了說明編碼轉換后,字段排序如何受影響,會結合mysql源代碼給出原因和分析。首先看測試用例,假設cmp_t(GBK編碼)和cmp_t2(UTF8編碼)分別是遷移前后的表。
測試用例:
| ? | 操作 | cmp_t(GBK) | cmp_t2(UTF8) |
| 1 | ? GBK表: select?c1,hex(c1) from?cmp_t; ? UTF8表: select?c1,hex(c1) from cmp_t2; | +------+---------+ | c1???|?hex(c1) | +------+---------+ |?一??| D2BB??? |?二??| B6FE |?三??| C8FD??? |?a????| 61????? | 1????| 31 +------+---------+????? | +------+---------+ | c1???|?hex(c1) | +------+---------+ |?一??| E4B880? |?二??| E4BA8C? |?三??| E4B889? |?a????| 61????? | 1????| 31????? +------+---------+ |
| 2 | GBK表: select?c1,hex(c1) from?cmp_t?where c1>’a’ order by c1; ? UTF8表: select?c1,hex(c1) from cmp_t2 where c1>’a’ order by c1; | +------+---------+ | c1???|?hex(c1) | +------+---------+ |?二??| B6FE????| |?三??| C8FD??? |?一??| D2BB??? +------+---------+ | +------+---------+ | c1???|?hex(c1) | +------+---------+ |?一??| E4B880? |?三??| E4B889? |?二??| E4BA8C? +------+---------+ |
?
從上面操作返回的結果我們可以得到以下幾點信息:
原理分析:
Mysql利用sortcmp函數對字符串進行比較,對于GBK的字符串和UTF8的字符串分別采用接口my_strnncollsp_gbk和my_strnncollsp_utf8比較,這兩個函數分別在ctype-gbk.c和ctype-utf8.c中實現,兩個函數實現邏輯類似,只是各有自己一套比較大小的規則,下面我主要描述下my_strnncollsp_utf8的比較邏輯和比較大小的規則。
比較邏輯:
附1:【接口: my_utf8_uni】
根據UTF8編碼規則,符合編碼規范的字符占用1-6個字節。
取字符串第一個字節?s
if?s<0x80
? ? ?表示字符占1個字節
elif?s<0xe0
? ? 表示字符占2個字節
elif?s<0xf0??
? ? 表示字符占3個字節
else?s<0xf8
? ? 表示字符占4個字節
elif?s<0xfc
? ?表示字符占5個字節
elif?s<0xfe
? ?表示字符占6個字節?
英文字符和數字字符編碼兼容ASCII,編碼值小于0x80,因此都只占1個字節;漢字的utf8編碼的首字節都在[0xe0,0xf0]之間,所以占3個字節。
附2:utf8編碼比較大小規則
value?= ((s[0] & 0x0f) << 12)| ((s[1] ^ 0x80) << 6) | (s[2] ^ 0x80)
s[0],s[1],s[2]表示組成漢字的三個字節,對參與比較的漢子字符進行計算得到value1和value2,通過比較value1和value2的大小,判斷字符大小。
附3:二進制比較【接口:?bincmp】
memcmp函數比較,即逐字節比較。
因此,如果業務上面需要依賴漢字比較的場景,需要考慮字符集升級(GBK->UTF8)的風險,主要是索引或主鍵中包含字符串字段需要特別關注,如果字符串中確定只包含有數字和字符,則不會存在問題。
?
?
?
總結
以上是生活随笔為你收集整理的字符集GBK升级UTF8的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GOOD MEETINGS CREATE
- 下一篇: qt5 make 找不到QApplica