问题导读:
1、Sqoop export有哪三种导出模式,Sqoop默认是哪个模式?
2、INSERT模式和UPDATE模式区别,各自应用场景?
3、--update-key 、--column-key、--export-dir参数各自的作用?
4、--update-mode参数有哪两种模式,区别是什么?
5、Sqoop 导出插入事务提交原理,一条插入语句包含多少条记录?多少条语句执行一次事务提交?
6、--update-mode参数默认后接的是updateonly吗?
7、如果一个Map task任务执行失败了会怎么样?之前已经提交的事务操作会回滚吗?
一、Sqoop export简介
Sqoop export工具被用来将文件集合从HDFS中导入到关系型数据库中。目标表必须事先已经在数据库中创建好。输入文件根据用户指定的分隔符被读取解析成记录集。Sqoop默认的是将这些操作转换成“INSERT模式”,向目标数据库中注入数据记录。在“更新模式”中,Sqoop将会产生更新语句替换数据库中已经存在的记录。在“调用模式”中,Sqoop会为每个记录产生一个存储过程调用。
“INSERT模式”:Sqoop默认将每条记录以转换成INSERT语句,添加到数据库表中,如果你的表存在一些约束如关键字唯一等,使用插入模式要当心,避免违反这些约束。如果一条记录插入失败那么,该导入job将会失败。这种模式一般用于将数据导入到一个新的、空的表。Sqoop默认情况下使用INSERT 模式
“UPDATE模式”:如果指定--update-key参数,Sqoop将会修改一个数据库中存在的数据集,每一条记录都会当做UPDATE语句来修改存在的记录。记录的修改语句根据--update-key指定的列决定。如果一个更新语句在数据库中没有对应的记录,则不会报错,导出操作会继续进行。事实上,这意味着不会在数据库中导入新的记录,只是更新原始数据。同样的,如果使用--column-key指定的列不是唯一标识行的,也就是说不是关键字,那么多个行记录将会被更新通过使用一条语句。
二、参数介绍
--update-key 后面也可以接多个关键字列名,可以使用逗号隔开,Sqoop将会匹配多个关键字后再执行更新操作。
--export-dir 参数配合--table或者--call参数使用,指定了HDFS上需要将数据导入到MySQL中的文件集目录。
--update-mode updateonly和allowinsert。 基于目标数据库,如果指定--update-mode模式为allowinsert,可以将目标数据库中原来不存在的数据也导入到数据库表中。
即将存在的数据更新,不存在数据插入。
三、使用默认INSERT模式导出
[hadoopUser@secondmgt ~]$ sqoop-export --connect jdbc:mysql://secondmgt:3306/spice --username hive --password hive --table sqoopusers2 --export-dir /output/query/ Warning: /usr/lib/hcatalog does not exist! HCatalog jobs will fail. Please set $HCAT_HOME to the root of your HCatalog installation. 15/01/18 19:06:06 WARN tool.BaseSqoopTool: Setting your password on the command-line is insecure. Consider using -P instead. 15/01/18 19:06:06 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset. 15/01/18 19:06:06 INFO tool.CodeGenTool: Beginning code generation 15/01/18 19:06:07 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `sqoopusers2` AS t LIMIT 1 15/01/18 19:06:07 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `sqoopusers2` AS t LIMIT 1 15/01/18 19:06:07 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /home/hadoopUser/cloud/hadoop/programs/hadoop-2.2.0 Note: /tmp/sqoop-hadoopUser/compile/fac73511c484d2d5abe0c007245594ff/sqoopusers2.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. 15/01/18 19:06:08 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-hadoopUser/compile/fac73511c484d2d5abe0c007245594ff/sqoopusers2.jar 15/01/18 19:06:08 INFO mapreduce.ExportJobBase: Beginning export of sqoopusers2 15/01/18 19:06:08 INFO Configuration.deprecation: mapred.job.tracker is deprecated. Instead, use mapreduce.jobtracker.address SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/home/hadoopUser/cloud/hadoop/programs/hadoop-2.2.0/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/home/hadoopUser/cloud/hbase/hbase-0.96.2-hadoop2/lib/slf4j-log4j12-1.6.4.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] 15/01/18 19:06:09 INFO Configuration.deprecation: mapred.jar is deprecated. Instead, use mapreduce.job.jar 15/01/18 19:06:09 INFO Configuration.deprecation: mapred.reduce.tasks.speculative.execution is deprecated. Instead, use mapreduce.reduce.speculative 15/01/18 19:06:09 INFO Configuration.deprecation: mapred.map.tasks.speculative.execution is deprecated. Instead, use mapreduce.map.speculative 15/01/18 19:06:09 INFO Configuration.deprecation: mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps 15/01/18 19:06:09 INFO client.RMProxy: Connecting to ResourceManager at secondmgt/192.168.2.133:8032 15/01/18 19:06:10 INFO input.FileInputFormat: Total input paths to process : 4 15/01/18 19:06:10 INFO input.FileInputFormat: Total input paths to process : 4 15/01/18 19:06:11 INFO mapreduce.JobSubmitter: number of splits:3 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.job.classpath.files is deprecated. Instead, use mapreduce.job.classpath.files 15/01/18 19:06:11 INFO Configuration.deprecation: user.name is deprecated. Instead, use mapreduce.job.user.name 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.cache.files.filesizes is deprecated. Instead, use mapreduce.job.cache.files.filesizes 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.cache.files is deprecated. Instead, use mapreduce.job.cache.files 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.reduce.tasks is deprecated. Instead, use mapreduce.job.reduces 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.mapoutput.value.class is deprecated. Instead, use mapreduce.map.output.value.class 15/01/18 19:06:11 INFO Configuration.deprecation: mapreduce.map.class is deprecated. Instead, use mapreduce.job.map.class 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.job.name is deprecated. Instead, use mapreduce.job.name 15/01/18 19:06:11 INFO Configuration.deprecation: mapreduce.inputformat.class is deprecated. Instead, use mapreduce.job.inputformat.class 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.input.dir is deprecated. Instead, use mapreduce.input.fileinputformat.inputdir 15/01/18 19:06:11 INFO Configuration.deprecation: mapreduce.outputformat.class is deprecated. Instead, use mapreduce.job.outputformat.class 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.cache.files.timestamps is deprecated. Instead, use mapreduce.job.cache.files.timestamps 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.mapoutput.key.class is deprecated. Instead, use mapreduce.map.output.key.class 15/01/18 19:06:11 INFO Configuration.deprecation: mapred.working.dir is deprecated. Instead, use mapreduce.job.working.dir 15/01/18 19:06:11 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1421373857783_0019 15/01/18 19:06:11 INFO impl.YarnClientImpl: Submitted application application_1421373857783_0019 to ResourceManager at secondmgt/192.168.2.133:8032 15/01/18 19:06:11 INFO mapreduce.Job: The url to track the job: http://secondmgt:8088/proxy/application_1421373857783_0019/ 15/01/18 19:06:11 INFO mapreduce.Job: Running job: job_1421373857783_0019 15/01/18 19:06:24 INFO mapreduce.Job: Job job_1421373857783_0019 running in uber mode : false 15/01/18 19:06:24 INFO mapreduce.Job: map 0% reduce 0% 15/01/18 19:06:34 INFO mapreduce.Job: map 33% reduce 0% 15/01/18 19:06:38 INFO mapreduce.Job: map 100% reduce 0% 15/01/18 19:06:38 INFO mapreduce.Job: Job job_1421373857783_0019 completed successfully 15/01/18 19:06:38 INFO mapreduce.Job: Counters: 29 File System Counters FILE: Number of bytes read=0 FILE: Number of bytes written=275307 FILE: Number of read operations=0 FILE: Number of large read operations=0 FILE: Number of write operations=0 HDFS: Number of bytes read=1130 HDFS: Number of bytes written=0 HDFS: Number of read operations=18 HDFS: Number of large read operations=0 HDFS: Number of write operations=0 Job Counters Launched map tasks=3 Other local map tasks=1 Data-local map tasks=1 Rack-local map tasks=1 Total time spent by all maps in occupied slots (ms)=134888 Total time spent by all reduces in occupied slots (ms)=0 Map-Reduce Framework Map input records=13 Map output records=13 Input split bytes=512 Spilled Records=0 Failed Shuffles=0 Merged Map outputs=0 GC time elapsed (ms)=159 CPU time spent (ms)=7260 Physical memory (bytes) snapshot=426471424 Virtual memory (bytes) snapshot=2651189248 Total committed heap usage (bytes)=251658240 File Input Format Counters Bytes Read=0 File Output Format Counters Bytes Written=0 15/01/18 19:06:38 INFO mapreduce.ExportJobBase: Transferred 1.1035 KB in 28.9938 seconds (38.9738 bytes/sec) 15/01/18 19:06:38 INFO mapreduce.ExportJobBase: Exported 13 records.查看结果:
mysql> select * from sqoopusers2; +----+-------------+----------+-----+-----------+------------+-------+------+ | id | username | password | sex | content | datetime | vm_id | isad | +----+-------------+----------+-----+-----------+------------+-------+------+ | 56 | hua | hanyun | 男 | 开通 | 2013-12-02 | 0 | 1 | | 58 | feng | 123456 | 男 | 开通 | 2013-11-22 | 0 | 0 | | 59 | test | 123456 | 男 | 开通 | 2014-03-05 | 58 | 0 | | 60 | user1 | 123456 | 男 | 开通 | 2014-06-26 | 66 | 0 | | 61 | user2 | 123 | 男 | 开通 | 2013-12-13 | 56 | 0 | | 62 | user3 | 123456 | 男 | 开通 | 2013-12-14 | 0 | 0 | | 64 | kai.zhou | 123456 | ? | ?? | 2014-03-05 | 65 | 0 | | 65 | test1 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 66 | test2 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 67 | test3 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 68 | sqoopincr01 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 69 | sqoopincr02 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 70 | sqoopincr03 | 113 | 男 | 未开通 | NULL | 0 | 0 | +----+-------------+----------+-----+-----------+------------+-------+------+ 13 rows in set (0.00 sec)由上查询结果可知,数据从HDFS中导出成功。导入操作被多个写操作并行的执行。每一个写操作使用一个不同的连接到数据库。这些有单独的事务。 Sqoop使用多行插入语法使每个语句插入到100条记录。 每100条语句,拥有Writer任务的当前事务会执行一次提交,100*100条记录会写入数据库表中。这将保证事务缓冲区不会无限制的增长和导致内存溢出。因此,一个导出操作不是原子过程。在导出结束之前,可以看到部分导出结果。
四、使用UPDATE模式导出数据
1、演示UPDATE模式导出数据,对表sqoopusers2表执行原表修改操作,将所有用户性别改为女,来展示UPDATE用法
mysql> update sqoopusers2 set sex='女'; Query OK, 13 rows affected (0.02 sec) Rows matched: 13 Changed: 13 Warnings: 0 mysql> select * from sqoopusers2; +----+-------------+----------+-----+-----------+------------+-------+------+ | id | username | password | sex | content | datetime | vm_id | isad | +----+-------------+----------+-----+-----------+------------+-------+------+ | 56 | hua | hanyun | 女 | 开通 | 2013-12-02 | 0 | 1 | | 58 | feng | 123456 | 女 | 开通 | 2013-11-22 | 0 | 0 | | 59 | test | 123456 | 女 | 开通 | 2014-03-05 | 58 | 0 | | 60 | user1 | 123456 | 女 | 开通 | 2014-06-26 | 66 | 0 | | 61 | user2 | 123 | 女 | 开通 | 2013-12-13 | 56 | 0 | | 62 | user3 | 123456 | 女 | 开通 | 2013-12-14 | 0 | 0 | | 64 | kai.zhou | 123456 | 女 | ?? | 2014-03-05 | 65 | 0 | | 65 | test1 | 111 | 女 | 未开通 | NULL | 0 | 0 | | 66 | test2 | 111 | 女 | 未开通 | NULL | 0 | 0 | | 67 | test3 | 113 | 女 | 未开通 | NULL | 0 | 0 | | 68 | sqoopincr01 | 113 | 女 | 未开通 | NULL | 0 | 0 | | 69 | sqoopincr02 | 113 | 女 | 未开通 | NULL | 0 | 0 | | 70 | sqoopincr03 | 113 | 女 | 未开通 | NULL | 0 | 0 | +----+-------------+----------+-----+-----------+------------+-------+------+ 13 rows in set (0.00 sec)2、执行命令
[hadoopUser@secondmgt ~]$ sqoop-export --connect jdbc:mysql://secondmgt:3306/spice --username hive --password hive --table sqoopusers2 --update-key id --export-dir /output/query/以id作为修改关键字,可以根据id匹配修改
3、查看结果
mysql> select * from sqoopusers2; +----+-------------+----------+-----+-----------+------------+-------+------+ | id | username | password | sex | content | datetime | vm_id | isad | +----+-------------+----------+-----+-----------+------------+-------+------+ | 56 | hua | hanyun | 男 | 开通 | 2013-12-02 | 0 | 1 | | 58 | feng | 123456 | 男 | 开通 | 2013-11-22 | 0 | 0 | | 59 | test | 123456 | 男 | 开通 | 2014-03-05 | 58 | 0 | | 60 | user1 | 123456 | 男 | 开通 | 2014-06-26 | 66 | 0 | | 61 | user2 | 123 | 男 | 开通 | 2013-12-13 | 56 | 0 | | 62 | user3 | 123456 | 男 | 开通 | 2013-12-14 | 0 | 0 | | 64 | kai.zhou | 123456 | ? | ?? | 2014-03-05 | 65 | 0 | | 65 | test1 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 66 | test2 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 67 | test3 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 68 | sqoopincr01 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 69 | sqoopincr02 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 70 | sqoopincr03 | 113 | 男 | 未开通 | NULL | 0 | 0 | +----+-------------+----------+-----+-----------+------------+-------+------+ 13 rows in set (0.00 sec)由结果可知,性别又被修改回来了。 UPDATE模式,默认是updateonly,即只将匹配到的--update-key进行更新,没有匹配到,但是源数据文件中存在的记录,不执行插入操作.现在我们使用allowinsert模式,使其修改匹配的记录,同时数据库中不存在的记录,源文件中存在的,执行插入操作。
五、使用--update-mode allowinsert模式
为了演示效果,我们删除部分sqoopusers2表中数据并做一些修改,如下:
1、删除以sqoop开头的用户名记录
2、将kai.zhou名字改为sqoop1.4.4
使数据库表中数据内容如下,注意前后对比!
mysql> select * from sqoopusers2; +----+------------+----------+-----+-----------+------------+-------+------+ | id | username | password | sex | content | datetime | vm_id | isad | +----+------------+----------+-----+-----------+------------+-------+------+ | 56 | hua | hanyun | 男 | 开通 | 2013-12-02 | 0 | 1 | | 58 | feng | 123456 | 男 | 开通 | 2013-11-22 | 0 | 0 | | 59 | test | 123456 | 男 | 开通 | 2014-03-05 | 58 | 0 | | 60 | user1 | 123456 | 男 | 开通 | 2014-06-26 | 66 | 0 | | 61 | user2 | 123 | 男 | 开通 | 2013-12-13 | 56 | 0 | | 62 | user3 | 123456 | 男 | 开通 | 2013-12-14 | 0 | 0 | | 64 | sqoop1.4.4 | 123456 | ? | ?? | 2014-03-05 | 65 | 0 | | 65 | test1 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 66 | test2 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 67 | test3 | 113 | 男 | 未开通 | NULL | 0 | 0 | +----+------------+----------+-----+-----------+------------+-------+------+3、执行命令
[hadoopUser@secondmgt ~]$ sqoop-export --connect jdbc:mysql://secondmgt:3306/spice --username hive --password hive --table sqoopusers2 --update-key id --update-mode allowinsert --export-dir /output/query/4、再次查看结果
mysql> select * from sqoopusers2; +----+-------------+----------+-----+-----------+------------+-------+------+ | id | username | password | sex | content | datetime | vm_id | isad | +----+-------------+----------+-----+-----------+------------+-------+------+ | 56 | hua | hanyun | 男 | 开通 | 2013-12-02 | 0 | 1 | | 58 | feng | 123456 | 男 | 开通 | 2013-11-22 | 0 | 0 | | 59 | test | 123456 | 男 | 开通 | 2014-03-05 | 58 | 0 | | 60 | user1 | 123456 | 男 | 开通 | 2014-06-26 | 66 | 0 | | 61 | user2 | 123 | 男 | 开通 | 2013-12-13 | 56 | 0 | | 62 | user3 | 123456 | 男 | 开通 | 2013-12-14 | 0 | 0 | | 64 | kai.zhou | 123456 | ? | ?? | 2014-03-05 | 65 | 0 | | 65 | test1 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 66 | test2 | 111 | 男 | 未开通 | NULL | 0 | 0 | | 67 | test3 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 68 | sqoopincr01 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 69 | sqoopincr02 | 113 | 男 | 未开通 | NULL | 0 | 0 | | 70 | sqoopincr03 | 113 | 男 | 未开通 | NULL | 0 | 0 | +----+-------------+----------+-----+-----------+------------+-------+------+ 13 rows in set (0.00 sec)由结果看,数据恢复正常。此处“调用模式”暂不介绍,用法其实也差不多,有兴趣,大家可以尝试使用看看。
六、错误分析
Export有时候会失败,可能有如下之一原因:
1、Hadoop集群与数据库失去连接(可能是硬件错误或者服务器软件崩溃)
2、试图插入数据库时违反了一致性约束条件(如关键字重复)
3、从HDFS源数据文件中试图解析一个不完全的或者不符合要求格式的数据记录
4、试图使用不正确的分隔符解析记录
5、容量问题(如:RAM容量或者磁盘容量不足等)
如果一个Map任务因为上述原因失败,那么会导致该导入Job失败。一个失败的导入结果是无法确定的。每一个导出Map任务以不同分隔开来的事务运行着。此外,单个Map任务每隔一段时间提交当前的事务,如果一个任务失败了,那么当前的事务会被回滚。先前提交的事务将会继续保存在数据库中,会导致一个不完全的导出操作。
推荐阅读:
上一篇:Sqoop1.4.4使用增量导入模式将MySQL数据库中数据导入到HDFS中
下一篇:Sqoop1.4.4将MySQL中数据导入到Hive表中