LoadData工具使用说明

最近更新时间: 2024-06-12 15:06:00

依赖

依赖库信息 ubuntu系列:apt-get install expat
centos系列:yum install expat expat-devel -y

原理

noshard表和global表对数据文件不切分,只是执行导入sql,区别是对于noshard表只导入一个set,global导入所有set。使用透传语法。 导入时使用多线程,根据定义的块大小对数据文件进行位置选取,线程获取文件块位置后通过多线程执行load data infile导入。 groupshard表、subshard二级分区表和range/list全局分区表都会进行多线程的切分和导入,区别在于切分阶段groupshard表使用每行数据的shardkey进行hash,然后结合每个set的hash范围获得要发往的setname,进而切分为子文件进行通过loaddatainfile导入。subshard二级分区表会在groupshard表的基础上再次细化每个set的数据文件,按照分区范围将发往同一个set的文本再次细化为发往一个set的某一个分区的文件。range/list表则根据分区范围或者list范围定位到要发往的set,再切分为文件通过load data infile发送。

架构设计

主线程根据设定的块大小(假设为64k)先获取64k大小的分块,再往后定位到行结束符,从而获得一个分块range=(begin_pos,end_pos)。由此将一个文件分为多个range存在队列里。再根据设定的线程数生成多个线程,每个线程从队列里取得一块数据的位置,判断表类型如为noshard或者global则直接发送该块数据内的数据,不生成中间文件。如为shard,一级分区表,二级分区,则按行读取该块数据内的数据,根据发往的set/分区的不同将数据切分到子文件中,再通过load data infile发送。线程处理完一个range后,如导入不出现警告或者报错则删除子文件,再处理其他range。如出现警告或者报错,则将报错子文件存于./tmp_error目录下,将警告子文件存放在./tmp_warning目录下,再取其他range继续处理。

功能介绍

  • 支持noshard单表,global复制表,groupshard分表,subshard二级分区表以及range/list全局分区表的导入。

  • 支持进度条显示,包括实时导入记录数,总进度百分比,实时导入速率,耗时等。

  • 支持命令行导入(类似--ip=127.0.0.1)和文件参数导入(配置文件load.ini)

  • 支持自定义导入线程,分割块(chunk_size)大小等参数。

  • 支持导入部分字段,使用 --fields ="(id,k,@jump,pad)"参数跳过第三列数据只导入3个字段,或者--fields ="(id,k)"导入两个字段。

  • 支持参数设定日志等级,当日志等级设置为debug时(--log_level=2)可以查看详细的报错信息,定位到具体的行。报错或者报警告的子文本会报错在./tmp_data目录下。

  • 支持后台运行,通过设置--is_daemon=true开启后台模式,开启后可通过信号量(kill -s SIGUSR1 pid)的方式获得实时的导入进度。同时log日志每隔5min打印进度。

  • 支持执行前置sql,通过参数--prefix_sqls能在导入前执行sql,对于设置net_read/write_timeout等参数也可以在此后追加,以分号隔开每个sql。目前默认运行"SET unique_checks = 0; SET foreign_key_checks = 0;SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"

  • 支持文件夹导入

  • 支持位置参数

  • 支持断点续传

  • 支持自动重试

  • 支持设定出错时是退出线程还是继续执行其他range导入

  • 支持参数开启文件列数与字段数检查功能

执行条件

  1. 执行load_data的用户需要有bin目录下的创建目录、创建文件的权限。

  2. TDSQL实例需要做如下设置(导入结束后需手动恢复):

    • 调整复制模式为异步复制

    • 开启Set免切设置

    • 尽量调大数据库超时参数net_read_timeout/net_write_timeout/innodb_lock_wait_timeout

    • 尽量调大数据库binlog拦截参数binlog_write_threshold

    • 数据库关闭双1参数sync_binlog/innodb_flush_log_at_trx_commit

    • 数据库开启LOCAL方式导入数据参数local_infile

    • 数据库磁盘空间检查(预计总量占用2~3倍CSV文件空间)

    • 需要预留足够内存

导入指令

导入指令有3种:命令行导入,位置参数导入和配置文件导入(执行./load_data 可以看到help信息。)

命令行导入:
./load_data --ip=127.0.0.1 --port=15026 --user=test --password=test --db_table=loaddata.sbtest_shard --file=sbtest_4l.txt --field_enclosed=" " --field_terminated=" " --thread_num=128 

位置参数导入(支持mode0/mode1/mode2/mode3/mode4):
/load_data mode0/mode1 proxy_host proxy_port user password db_table shardkey_index file field_terminate filed_enclosed [split_size] [escaped by]
example:
   example:./load_data mode1 10.10.10.10 3336 test test123 shard.table  1 '/tmp/datafile'  ' ' ''
   mode0: 只拆分数据,不进行数据导入。
   mode1:用insert ignore导入的方式,并且skip_error是false,遇见错误直接退出。
   mode2:用insert ignore导入的方式,并且skip_error是true,遇见错误不停止。
   mode3:用replace 导入方式,并且skip_error是false,遇见错误直接退出。
   mode4:用replace 导入方式,并且skip_error是true,遇见错误不停止。

配置文件导入:
./load_data –config=load.ini
其中load.ini格式参考文件load.ini

配置参数说明

常用参数:
  --help   说明:获取帮助信息
  --ip=127.0.0.1 说明:proxy的ip地址
  --port=15006   说明:proxy的端口
  --user=test    说明:登陆proxy的用户名
  --password=test 说明:登陆proxy的秘密
  --db_table=test.test 说明:指定需要导入的库名和表名,如test.sbtest
  --file=data200M.txt  说明:导入文件的位置,如--file=/data2/load_new/2.txt;当为目录时,表示文件夹导入。
  --field_terminated=" "  说明:字段间隔符,如空格(" "),逗号(","),制表符("\t" )等
  --field_enclosed=" "    说明:字段括起符,如为空(" "),双引号号("\"")等,注:双引号在命令行和配置文件中有区别
  --fields_optionally_enclosed=false 说明:是否选择性括住CHAR、VARCHAR和TEXT等字符型字段
  --thread_num=1          说明:导入线程数,默认值为1
  --chunk_size=10         说明:导入块大小(KB)默认值为与文件大小相关的一个分段函数
  --config=load.ini 说明:配置文件导入模式,配置此参数后,其他直接读取配置文件的参数配置。

不常用参数:
  --escaped_by="\\"       说明:转义字符,默认值为反双斜线
  --lines_terminated="\n"  说明:行间隔符
  --prefix_sqls="SET foreign_key_checks"   说明:前置运行sql,默认运行"SET unique_checks = 0", "SET foreign_key_checks = 0","SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"这3条sql。注:prefix_sqls在命令行和配置文件中有区别
  --replace_duplicates=false   说明:是否开启替换模式,替换已存在的记录
  --fields="(id,k,@jump,pad)"   说明: 导入部分字段(id,k,@jump,pad)
  --log_level=5   说明:设置日志等级,默认为LOG_INFO,开启debug日志请将等级设置为2
  --is_daemon=false 说明:是否开启后台运行模式,默认关闭
  --retry=1  说明:设置重试模式。-1表示当导入出现错误时一直重连;0表示不重试;1表示重试一段时间,需结合retry_time一起使用
  --retry_time=10 说明:当retry为1时,指定重试时间,单位是小时,默认一个小时
  --skip_error=0 说明:是否跳过错误,即当发生错误时,是停止导入(0)还是跳过错误(1)。
  --Breakpoint=0 说明:是否开启断点重传
  --client_timeout=10 说明,mysql api的超时参数,默认是10s.
  --column_check=0 说明:是否开启字段检查功能,注意此功能与导入部分字段功能冲突,无法同时使用

举例说明

假设有表test:
CREATE TABLE `test` (
  `a` int(30) NOT NULL,
  `b` int(30) DEFAULT NULL,
  `c` int(30) NOT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

已有数据文件test1.txt格式如下:
"1","11","111"
"2","22","222"
将test.txt导入test表可以使用下面指令开启2个线程导入:
./load_data  --ip=127.0.0.1 --port=15009  --user=test --password=test --db_table=loaddata.test --file=/data1/test1.txt --field_enclosed="\"" --field_terminated="," --thread_num=2;

已有数据文件test2.txt格式如下:
"1","aaa","11","111"
"2","bbb","22",,"222"
想要跳过test2.txt的第二列数据,将数据导入表test,可以使用以下指令:
./load_data  --ip=127.0.0.1 --port=15009  --user=test --password=test --db_table=loaddata.test --file=/data1/test1.txt --field_enclosed="\"" --field_terminated="," --thread_num=2 --fields="(a,@jump,b,c)";

已有数据文件test3.txt格式如下:
"1",,"111"
"2",,"222"
想将第二列的空值导入表中为NULL,可以使用fields参数来实现,具体指令如下:
./load_data  --ip=127.0.0.1 --port=15009  --user=test --password=test --db_table=loaddata.test --file=/data1/test3.txt --field_enclosed="\"" --field_terminated="," --thread_num=2 --fields="(a, @b, c) SET b = NULLIF(@b,'')";

问题定位

  • 问题描述: load data failed, errmsg: ret: -1, errno: 2013: info: query error[gone away agin]

      问题原因:导入连接中断,可以尝试降低线程数和块大小再重新导入。
  • 问题描述:"Local_infile is OFF! Input /sets:allsets/set global local_infile='ON';"

      问题原因:导入权限未开启,连接proxy,运行指令/sets:allsets/set global local_infile='ON';或者使用赤兔开启权限。
  • 问题描述:配置文件设置参数prefix_sqls="CREATE DATABASE IF NOT EXISTS test",运行时query sql failed

      问题原因:配置文件中prefix_sqls参数设置时,需要去掉双引号。

日志查看

  • 默认情况下,日志等级为LOG_INFO,只会显示info和warning,error信息,想要查看更多信息,可以通过--log_level参数将日志等级设为2,即可查看debug信息。

  • load_data会产生两个日志文件:文件名.discard.log和文件名.log

    文件名.discard.log:收集切分时shardkey不符合要求的数据行。比如当括起符为双引号时,如果导入数据中shardkey字段缺少半边引号94",或者""," "时,会认为数据格式有问题,将该条数据写入discard.log。如果开启column_check后,多列或者少列的错误行会记录到此日志。

    文件名.log:导入阶段报错或者警告的行会在文件名.log中体现,同时该日志也会有整体导入进度的信息,导入进度每隔5min打印一次,尾部也会打印进度信息。

其他

  • Chunk_size的自适应使用分段函数,当用户未设置chunk_size参数时,

    当文件<=10k时,chunk_size=1k

    当10k<文件<100M时,chunk_size=(文件/10k)k

    当100M<文件<=10G时,chunk_size=(文件/100k)k

    当10G<文件时,chunk_size=100M

  • 配置文件中,如果括起符为双引号时,参数设置和命令行稍有区别,配置文件为 --field_enclosed=""",区别于命令行的--field_enclosed="""

  • prefix_sqls参数的设定在使用配置文件时,需要去掉引号