多线程使用 load data infile 时 发现插 50w 数据 数据库只有十几万 框架使用的是 mybatis 使用拦截器拦截底层 sql 然后通过流去写数据库
一开始认为是线程的问题 在插入数据的方法上加了 同步锁 发现还是只有十几万数据
现在怀疑是底层数据库 io 的问题
不知道有什么好思路吗?谢谢
1
notgod 2016-06-05 19:00:55 +08:00 1
#1 Check 硬盘是不是有逻辑坏道
#2 比较 2 次 Load 中断的地方是不是一致 #3 比较 2 次 Load 插入的条目是不是一致 #4 将 50W 的 file, split 为 10w / 个 然后一个一个来 试试 最后就差不多可以定位出问题在哪里了 load data infile 文件 和 my.cnf 里的有个什么 size / time 也有一定关系 IO 基本不会有问题 MYSQL 比较成熟 有人做数据仓储 N 亿级的数据测试也无问题 |
2
iyaozhen 2016-06-05 19:46:23 +08:00 via Android 1
这种情况很可能是中间哪个数据不合法,写入不了。可以加个 ignore 参数
|
3
BOYPT 2016-06-05 19:46:39 +08:00 1
公司也有台机器也是这么弄的,我配置了 crontab 自动入库,然而时不时找我说弄到一半就没在库里。
我登陆进去发现,因为 mysqld 占用内存太大被内核 kill 了 |
4
notgod 2016-06-05 19:48:23 +08:00 1
|
5
MonkeyDLuffy OP |
6
MonkeyDLuffy OP @notgod 目前是 50w 数据 存在一个 array 里面 开 50 个线程 每个线程负责 1w 数据的插入 使用 mybatis 拦截器 50 个线程的调用 转换成 50 次 load data infile 的调用
|
7
MonkeyDLuffy OP 如果用一个线程操作 数据库是不会少的 多个线程就会出现这个情况
|
8
BOYPT 2016-06-06 13:58:15 +08:00
我后来是在脚本里面用 split 命令分割了文件,分批 load data
TEMPDIR=$(mktemp -d) /usr/bin/split -l 50000 --suffix-length=5 $LOG "$TEMPDIR/db_" SQL="" for LOG in $(ls $TEMPDIR); do SQL=$SQL"LOAD DATA LOCAL INFILE '$TEMPDIR/$LOG' INTO TABLE tbl_log_infos FIELDS TERMINATED BY '^A' (fld_time, fld_ip, fld_domain, fld_url, fld_title, fld_referrer, fld_high_ratio, fld_wide_ratio, fld_color_depth, fld_language, fld_drcom_tag, fld_client);" done 这样组合好一大堆 SQL 后再一次过喂给 mysql client |