这篇文章有不少废话,只是为了发泄一下。如果读者找需要解决的问题的办法,直接无视这些废话。
本文章为原创,转载文章请注明出处: http://blog.csdn.net/tianxiagongzheng/article/details/71812876
最近做的项目要将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文件。刚开始的时候容易遇到 ERROR 1290 (HY000),解决办法见我的另一篇博客http://blog.csdn.net/tianxiagongzheng/article/details/71037734 。用load data 将csv文件导入mysql 速度很快,其他方法对于大文件来说都显得太慢。
第三次倒腾的时候,我导出了一个1G多的csv文件,文件需要转成utf-8编码格式。可是notepad++不能打开直接打开这么大的文件,于是开始了我的艰难的转码过程。
如果知道文件的编码格式当然容易转码,再次强调一下,这不是gbk, gb2312 格式,在linux下执行file命令,得到如下信息: Non-ISO extended-ASCII text, with very long lines, with CRLF, NEL line terminators。
在网上搜索,终于找到一篇靠谱的博客:
http://blog.csdn.net/niityzu/article/details/42494477 ,这篇文章的关键是:
- $ iconv --list | sed 's/\/\/$//' | sort > encodings.list
- $ for a in `cat encodings.list`; do
- printf "$a "
- iconv -f $a -t UTF-8 systeminfo.txt > /dev/null 2>&1 \&& echo "ok: $a" || echo "fail: $a"
- 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命令导入了,想的太简单了。
在执行load data 的时候,出现了如下错误:
ERROR 29 (HY000): File '/var/lib/mysql-files/my_1G.csv' not found (Errcode: 13 - Permission denied)
尼玛。。。
还是网上搜索,有:http://www.linuxidc.com/Linux/2012-02/55533.htm,
摘抄如下 # 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分多钟后,终于报执行成功了。。。。。。
皇天不负有心人,有心人,终不负。。。。。。。。
这次的磨难终于结束了。