美文网首页MySQL
scadb系列--数据导入导出功能

scadb系列--数据导入导出功能

作者: 何约什 | 来源:发表于2017-09-08 20:14 被阅读73次

    数据管理功能的重要性

    MySQL可以支持多种数据备份和数据导出功能,其中mysqldump可以把数据导出到执行机器上,并且可以包含建表语句,而还有一种常见的是采用select ... into outfile..来把数据导出成格式化的数据,对于后者,MySQL还对应与导出文件对应的load data infile功能,可以快速的把数据导入到MySQL表中。通过这样的数据文件管理,可以方便数据在不同平台之间的分享和再次加工处理。

    scadb在数据管理上的考量

    scadb是一套分布式的MySQL中间件,如果没有数据管理功能,一旦需要数据管理,就需要DBA去底层MySQL中把数据从各个分区表中导出合并,既增加了DBA的工作量,也容易造成不必要的故障。
    所以笔者在开发scadb的时候,首先考虑的就是如何管理数据。而且考虑实现的方便性以及性能方面的考量,导出采用select ...into outfile,导入采用load data infile的方式。但是我们知道MySQL在导出和导入数据时,都是操作一个文件;而对于scadb来说,如果操作一个文件那么效率肯定无法让人满意,一旦数据库上亿条,导入导出会非常慢,而且无法把主机资源利用起来。
    并发显然是最好的方式,这也符合分布式系统的特点。所以在scadb上,笔者采用了基于目录的导入导出,两个语法中指定的不是一个文件,而是一个目录,由scadb根据需要在相应的目录下创建和读取文件,从而充分的调动系统资源,加快海量数据的导入导出速度。

    scadb数据导出

    导出语法例子:select * into outfile 'a' from a
    在该例子中,我们会从scadb中把a表的数据导出到a目录下,scadb的表对应到多个MySQL分区表,可以在多个MySQL分区表中同时执行导出,并生成多个文件。

    如何从MySQL中导出数据?

    导出数据,如图中所示,最终文件需要存储在scadb所在主机,而MySQL的select ..... into outfile语法会把数据格式化导出,但是它导出的数据是存放在MySQL实例所在服务器上,为了把文件传到scadb所在主机,可以在MySQL实例所在机器部署一个进程,如:Vitess的方案所示:

    vitess.png

    Vitess为每个MySQL对应部署一个vttablet进程。这样应用和应用部署的复杂度都会大大增加,这与scadb的轻量级设计相悖。

    scadb导出使用的方案图如下,显然不能使用MySQL的select ... into outfile功能。

    dump-out.png

    为了解决这个问题,笔者改造了MySQL,开发了新的语法select ... into localfile,该语法会把格式化好的数据通过记录的形势发送到客户端,举个栗子:

    mysql> select * into localfile 'a' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' from b \G
    *************************** 1. row ***************************
    send_cnt: 80
    send_data: 1,"ttt113ffadsf3czdsfad"
    2,"12313ffadsf3czdsfadf"
    3,"12313ffadsf3czdsfadf"
    ...
    *************************** 2. row ***************************
    send_cnt: 77
    send_data: 81,"ttt113ffadsf3czdsfad"
    82,"12313ffadsf3czdsfadf"
    83,"12313ffadsf3czdsfadf"
    84,"33313ffadsf3czdsfadf"
    ....
    
    

    该语法与普通的查询语法类似,但是返回的字段总是两个字段:

    send_cnt: 记录行数
    send_data: 格式化的记录数据
    

    通过这种方式,我们可以通过执行一条普通的SQL语句一样,获取到的格式化的数据集,把这些数据集保存到对应的文件中。

    select * into localfile ‘a’ from a_0 -----> a/a_0.txt
    select * into localfile ‘a’ from a_1 -----> a/a_1.txt
    select * into localfile ‘a’ from a_2 -----> a/a_2.txt
    ...............
    select * into localfile ‘a’ from a_99 -----> a/a_99.txt
    

    后续我会专门写篇文章介绍如何在MySQL上实现该功能。

    scadb数据导入

    scadb数据导入方案与数据导出类似,但是有一个点是相对复杂一点的,那就是数据导入在内部分为两个步骤:

    • 格式化数据
      把输入目录下的数据按照分区格式化成对应分区的数据,这里需要对目录下的所有的文件的每一行数据进行分析,它属于哪个分区,确定好分区,再把它放到对应规范化的分区数据文件中。
      性能考虑:因为有可能处理的数据量过大,所以在这里需要考虑并行化处理这些记录,笔者按照数据块进行分解,每个任务负责处理数据块,然后把每个任务交给一个线程池去处理。

    • 导入数据
      这一步与数据导出功能类似,对于应用程序来说发起了一个load data infile,而对应到每个分区文件,系统会采用load data local infile语法来把数据导入到对应的分区表中。

    dump-in.png

    scadb导入导出的并发度控制

    有了数据导出方案,还得考虑一个问题,就是导出数据的并发度,导出数据并发度过高,就会造成资源过滤使用,如果系统是个线上系统,可能会影响线上服务;如果并发度过低,导入导出就会过慢。所以我们需要按需找到平衡点。

    由于系统的差异性,笔者把控制权交给调用者,系统在load data和 select ... into outfile语法前面可以添加hint,来指定并发度。
    例如:

    /*!scadb:concurrent=10*/select * into outfile 'a' from a;
    以并发度10导出数据,最多同时执行10个分区表导出
    
    /*!scadb:step=1 concurrent=10*/load data infile 'a' into table a;
    以并发度10执行导入数据的第一步;
    

    相关文章

      网友评论

        本文标题:scadb系列--数据导入导出功能

        本文链接:https://www.haomeiwen.com/subject/yaynjxtx.html