1. 程式人生 > > linux下大檔案編碼轉碼及將oracle中資料匯入mysql

linux下大檔案編碼轉碼及將oracle中資料匯入mysql

        這篇文章有不少廢話,只是為了發洩一下。如果讀者找需要解決的問題的辦法,直接無視這些廢話。    

        最近做的專案要將Oracle中資料匯入Mysql, 資料量約有兩千萬條,慶幸的是隻有一張表,而且資料結構比較簡單。在這個過程中遇到不少坑,現在一 一記錄下來。

        首先說一下Mysql的環境是 Centos 7, Oracle是Windows系統下的。

        第一,第二次倒騰的時候,我將Oralcle表中的資料以100萬條為單位,匯入到20個csv檔案中,每個檔案有60M上下,匯出的csv檔案是預設的編碼格式,但是具體是什麼編碼格式不知道,反正不是你自以為的gbk,gb2312,這為後面一次性匯出匯入一個大檔案的悲劇埋下了伏筆。

       為了先測試匯入Mysql的效果,我先建一個2M的檔案test.csv。在linux下開啟測試檔案,一堆亂碼。然後我在Windows下用notepad++將每一個檔案先轉碼成utf-8的無bom格式,然後傳到linux下,進入Mysql,挨個用load data命令執行匯入csv檔案。剛開始的時候容易遇到

        第三次倒騰的時候,我直接用了匯出了一個1G多的csv檔案,直接在linux下用vim開啟當然還是亂碼,需要轉成utf-8編碼格式。可是notepad++不能開啟直接開啟這麼大的檔案,於是開始了我的艱難的轉碼過程。

        如果知道檔案的編碼格式當然容易轉碼,再次強調一下,這不是gbk, gb2312 格式,在linux下執行file命令,得到如下資訊:   Non-ISO extended-ASCII text, with very long lines, with CRLF, NEL line terminators。

在網上搜索,終於找到一篇靠譜的部落格:

  1. $ iconv --list | sed 's/\/\/$//' | sort > encodings.list  
  2. $ for a in `cat encodings.list`; do  
  3.   printf "$a  "  
  4.   iconv -f $a -t UTF-8 systeminfo.txt > /dev/null 2>&1 \&& echo "ok: $a" || echo "fail: $a"  
  5. done | tee result.txt  

注意systeminfo.txt 是你自己要轉碼的檔案。

悲催的是,我沒有那麼幸運能直接找到正確的編碼。

由於我的檔案很大,先建了一個只有1000條記錄的檔案,沒有起作用。於是我又建了一個大概2M的temp.csv檔案,執行後,result.txt中居然有好多ok,我去.........

這是逼我發飆啊。

於是我將上面的程式碼放到了一個指令碼中,如下:

 for a in `cat encodings.list`; do
  printf "$a  "
  iconv -f $a -t UTF-8  temp.csv > /home/myfile/$a.txt  && echo "ok: $a" || echo "fail: $a"  
done | tee result.txt

要知道共有一千一百多個編碼啊,生成了一千一百多個檔案(這一千一百多個檔案的檔名就是生成檔案的編碼格式)。看了一下result.txt檔案中,依然是有好多ok。

於是用find 命令 在這一千一百多個檔案中查詢某個 中文 字串,比如temp.csv中有 “你好嗎”,我就查詢“你好嗎”三個字,謝天謝地,只有11個檔案有這三個字。好了,我用這11一個編碼格式挨個對我的1個多G的檔案進行編碼轉換:

iconv -f xxx編碼 -t UTF-8 my_1G.csv >my_1G.csv  

這11個編碼格式快試完了,依然都是出錯,我近乎絕望的時候,奇蹟發生了,居然成了,這個格式是GB18030, 

有心人,終不負。。。終於成了。我長長長的舒了口氣。

你以為可以在Mysql中直接用load data命令匯入了,NO, NO ...老天折磨人的惡趣味永遠都沒有停止的時候。

在執行load data 的時候,出現瞭如下錯誤:

ERROR 29 (HY000): File '/var/lib/mysql-files/my_1G.csv' not found (Errcode: 13 - Permission denied)

尼瑪。。。

摘抄如下 # setsebool -P mysqld_disable_trans=1  

Ubuntu下 ,可以對AppArmor(/etc/apparmor.d/usr.sbin.mysqld) 修改,類似selinux。  新增/etc/squid/lists/eighties.txt w,類似。  

重啟Mysql,沒有作用。

再次絕望, 這個坑再次折磨了我很久。

我不死心,將以前的100萬條的小檔案執行了load data 命令,沒有問題,這說明不是Mysql 的問題。

無奈之下。我將 my_1G.csv 按照每百萬行一個檔案進行了分割,然後對分割後的第一個檔案xaa執行load data,居然成功了。。。。

於是我靈感來了,用cp命令將  my_1G.csv 複製了一份 ,對複製後的檔案my_1G_new.csv執行load data,終於不再報ERROR 29 (HY000)了,

於是靜靜加忐忑地等待,在5分多鐘後,終於報執行成功了。。。。。。

皇天不負有心人,有心人,終不負。。。。。。。。

這次的磨難終於結束了。

.