場景說明:
1、現上幾百台mysql數據庫,字符編碼latin1,現在需要做一個活動,將現上mysql數據庫的一些活動數據同步到一台mysql匯總數據庫(latin1),然後再將數據同步oracle中,最後官網顯示。
2、oracle是活動庫,字符集是ZHS16GBK,由於還有很大一部分數據都在oracle庫中,所以需要將mysql中的數據同步到oracle中。
3、mysql中有一個字段name,內容是中文、各種火星文。
4、官網是用java開發的,所有項目都是以utf8編碼的。
首先需要簡單了解幾個編碼:
1、latin1是ISO-8859-1的別名,ISO-8859-1編碼是單字節編碼,因此在支持ISO-8859-1的系統中傳輸和存儲其他任何編碼的字節流都不會被拋棄。
換言之,把其他任何編碼的字節流當作ISO-8859-1編碼看待都沒有問題。這是個很重要的特性,MySQL數據庫默認編碼是Latin1就是利用了這個特性。
ASCII編碼是一個7位的容器,ISO-8859-1編碼是一個8位的容器。
2、gbk,這個就不用說了,漢子的國標碼,專門用來表示漢字,是雙字節編碼,gbk是gb2312的子集,gb2312是gb18030的子集。
3、utf8,這是一個變長編碼,它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。
通過java程序解決思路:
1、將從mysql,iso-8859-1查詢出來,再轉成gbk的編碼存儲到oracle中,然後再以gbk的方式讀出來官網顯示。部分顯示沒有問題,但是gb18030無法顯示火星文,很多火星文都顯示成?。
2、將從mysql以utf8的編碼讀出,以utf8的編碼存儲到oracle中。這部分果斷不行,為什麼?因為mysql是latin1的編碼,以utf8的編碼是無法正常讀出的,全部是亂碼。
3、將mysql以ISO-8859-1的編碼讀出來,然後轉成utf8,再以utf8的編碼存儲到oracle中。iso無法正常轉成utf8,是不兼容的。
以上方法無法正常進行編碼轉換,只能在匯總數據庫這邊著手了。如果將匯總mysql的數據庫轉成utf8的,那麼java程序就能正常顯示。開始吧!!!
匯總數據庫是能正常查看數據庫的火星文的,linux支持比java要好多了,可能是由於開源與不開源的問題吧。
1、將數據庫進行邏輯備份:
mysqldump --default-character-set=latin1 -q --single-transaction -t db_collect table1 table2 >db_collect.sql
2、重新創建ut8庫和表結構
3、通過linux下面的iconv命令進行轉碼
LANG=en_US
CRT=default
sed -i 's/latin1/utf8/g' db_collect.sql
iconv -f gb18030 -c -t UTF-8 db_collect.sql -o db_collect_result.sql
mysql -f db_collect2 < db_collect_result.sql
4、調整系統編碼和CRT編碼
LANG=en_US.UTF-8
CRT=UTF-8
5、正常顯示數據,通過java程序以utf8的編碼方式查看,展示正常。
有個問題,為什麼java把latin1的轉成gb18030火星文無法顯示,在linux下用iconv命令轉就可以呢?latin1不能直接轉成gb18030,只能以gb18030編碼為基礎,再轉給能夠支持火星文的utf8.
顯示沒有問題了,但是新問題出現了,每次這樣轉碼,會導致數據庫無法使用。當然也可以增量進行轉碼,再導入,不過這樣太麻煩了。
最後通過一個php腳本解決問題:直接從上百台數據庫以默認的編碼查詢數據,再通過iconv轉成utf8編碼,直接insert到utf8表中。
但是這裡需要注意的是,在insert前需要set names utf8;系統編碼需要改成utf8.
php腳本:
$total_conn = open_mysql($total_mysql[1], $total_mysql[2], $total_mysql[3], $total_mysql[4]);
mysql_query("set names utf8;",$total_conn);
...省略
$total_sql = "insert into db_collect2.table1(name) values ('".iconv('gb18030','UTF-8',$list["name"])."');"
mysql_query($total_sql, $total_conn);
...省略
執行腳本:
export LANG=en_US.UTF-8
php /tmp/collect.php