Connection Resets When Importing from Oracle with Sqoop

Jul 15, 2013 / By André Araújo

Tags: , , , , , ,

I’ve been using Sqoop to load data into HDFS from Oracle. I’m using version 1.4.3 of Sqoop, running on a Linux machine and using the Oracle JDBC driver with JDK 1.6.

I was getting intermittent connection resets when trying to import data. After much troubleshooting, I eventually found the problem to be related to a known issue with the JDBC driver and found a way to work around it, which is described in this post.

The problem

I noticed that when I was importing data at times where the machine I was using to run the Sqoop client was mostly idle, everything would run just fine. However, at times when others started to work on the same machine and it became a bit busier, I would start to get the errors below intermittently:

[araujo@client ~]$ sqoop import --connect jdbc:oracle:thin:user/pwd@host/orcl -m 1 --query 'select 1 from dual where $CONDITIONS' --target-dir test
13/07/12 09:35:39 INFO manager.SqlManager: Using default fetchSize of 1000
13/07/12 09:35:39 INFO tool.CodeGenTool: Beginning code generation
13/07/12 09:37:53
ERROR manager.SqlManager: Error executing statement: java.sql.SQLRecoverableException: IO Error: Connection reset
	at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:467)
	at oracle.jdbc.driver.PhysicalConnection.(PhysicalConnection.java:546)
        ...
Caused by: java.net.SocketException: Connection reset
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:96)
	at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
	... 24 more

After some troubleshooting and googling, I found that the problem seemed to be related to the issue described in the following articles:

http://stackoverflow.com/questions/2327220/oracle-jdbc-intermittent-connection-issue/
https://forums.oracle.com/message/3701989/

Confirming the problem

To ensure the problem was the same as the one described in the articles and not something else intrinsic to Sqoop, I created a small Java program that simply connected to the database. I was able to reproduce the issue using it:

[araujo@client TestConn]$ time java TestConn
Exception in thread "main" java.sql.SQLRecoverableException: IO Error: Connection reset
...
Caused by: java.net.SocketException: Connection reset
...
	... 8 more

real    1m20.481s
user	0m0.491s
sys	0m0.051s

The workaround suggested in the articles also worked:

[araujo@client TestConn]$ time java -Djava.security.egd=file:/dev/../dev/urandom TestConn
Connection successful!

real    0m0.419s
user	0m0.498s
sys	0m0.036s

Applying the fix to Sqoop

It took me a while to figure out how to use the workaround above with Sqoop. Many tentatives to specify the parameter in the Sqoop command line, in many different forms, didn’t work as expected.

The articles mention that the java.security.egd parameter can be centrally set in the $JAVA_HOME/jre/lib/security/java.security file. Unfortunately, this didn’t work for me. Using strace, I confirmed that Sqoop was actually reading the java.security file but the setting just didn’t take effect. I couldn’t figure out why not and eventually gave up that alternative.

After a bit more of stracing and troubleshooting, though, I finally figured a way out.

Sqoop seems to use the JDBC driver in two different ways:

  • First, it connects to the Oracle database directly. It does that to gather more information about the tables (or query) from where the data is extracted and generate the map reduce job that it will run.
  • Second, the map reduce job generated by Sqoop uses the JDBC driver to connect to the database and perform the actual data import.

I was hitting the problem in the first case above, but I believe that in both cases there’s a potential for the problem to occur. So ideally, we should apply the workaround to both cases.

The Sqoop documentation clearly gives us an option to address the second case: using the following parameter to Sqoop allows us to pass Java command line options to the map reduce job:

sqoop import -D mapred.child.java.opts="-Djava.security.egd=file:/dev/../dev/urandom" ...

Even though I couldn’t fully prove the above, since I couldn’t consistently reproduce the problem for the map reduce tasks, I believe (and hope) it should work well.

The Sqoop direct connection to Oracle

The problem with the direct connection from Sqoop to Oracle, though, wasn’t resolved by that option. Trying to pass the “-Djava.security.egd=file:/dev/../dev/urandom” option directly to Sqoop didn’t work either.

After digging up a bit I found that the sqoop command eventually calls ${HADOOP_COMMON_HOME}/bin/hadoop to execute the org.apache.sqoop.Sqoop class. Since the hadoop executable is used, it accepts Java command line options through the HADOOP_OPTS environment variable.

A quick test confirmed that the case was closed:

[araujo@client STimport]$ export HADOOP_OPTS=-Djava.security.egd=file:/dev/../dev/urandom
[araujo@client STimport]$ sqoop import -D mapred.child.java.opts="-Djava.security.egd=file:/dev/../dev/urandom" --connect jdbc:oracle:thin:user/pwd@host/orcl -m 1 --query 'select 1 from dual where $CONDITIONS' --target-dir test 
13/07/12 10:08:17 INFO manager.SqlManager: Using default fetchSize of 1000
13/07/12 10:08:17 INFO tool.CodeGenTool: Beginning code generation
13/07/12 10:08:18 INFO manager.OracleManager: Time zone has been set to GMT
13/07/12 10:08:18 INFO manager.SqlManager: Executing SQL statement: select 1 from dual where  (1 = 0) 
13/07/12 10:08:18 INFO manager.SqlManager: Executing SQL statement: select 1 from dual where  (1 = 0) 
13/07/12 10:08:18 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/bin/../lib/hadoop-0.20-mapreduce
13/07/12 10:08:18 INFO orm.CompilationManager: Found hadoop core jar at: /opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/bin/../lib/hadoop-0.20-mapreduce/hadoop-core.jar
Note: /tmp/sqoop-araujo/compile/02ed1ccf04debf4769910b93ca67d2ba/QueryResult.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
13/07/12 10:08:19 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-araujo/compile/02ed1ccf04debf4769910b93ca67d2ba/QueryResult.jar
13/07/12 10:08:19 INFO mapreduce.ImportJobBase: Beginning query import.
13/07/12 10:08:19 WARN mapred.JobClient: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
13/07/12 10:08:21 INFO mapred.JobClient: Running job: job_201306141710_0075
13/07/12 10:08:22 INFO mapred.JobClient:  map 0% reduce 0%
13/07/12 10:08:31 INFO mapred.JobClient:  map 100% reduce 0%
13/07/12 10:08:33 INFO mapred.JobClient: Job complete: job_201306141710_0075
13/07/12 10:08:33 INFO mapred.JobClient: Counters: 23
13/07/12 10:08:33 INFO mapred.JobClient:   File System Counters
13/07/12 10:08:33 INFO mapred.JobClient:     FILE: Number of bytes read=0
13/07/12 10:08:33 INFO mapred.JobClient:     FILE: Number of bytes written=179438
13/07/12 10:08:33 INFO mapred.JobClient:     FILE: Number of read operations=0
13/07/12 10:08:33 INFO mapred.JobClient:     FILE: Number of large read operations=0
13/07/12 10:08:33 INFO mapred.JobClient:     FILE: Number of write operations=0
13/07/12 10:08:33 INFO mapred.JobClient:     HDFS: Number of bytes read=87
13/07/12 10:08:33 INFO mapred.JobClient:     HDFS: Number of bytes written=2
13/07/12 10:08:33 INFO mapred.JobClient:     HDFS: Number of read operations=1
13/07/12 10:08:33 INFO mapred.JobClient:     HDFS: Number of large read operations=0
13/07/12 10:08:33 INFO mapred.JobClient:     HDFS: Number of write operations=1
13/07/12 10:08:33 INFO mapred.JobClient:   Job Counters 
13/07/12 10:08:33 INFO mapred.JobClient:     Launched map tasks=1
13/07/12 10:08:33 INFO mapred.JobClient:     Total time spent by all maps in occupied slots (ms)=7182
13/07/12 10:08:33 INFO mapred.JobClient:     Total time spent by all reduces in occupied slots (ms)=0
13/07/12 10:08:33 INFO mapred.JobClient:     Total time spent by all maps waiting after reserving slots (ms)=0
13/07/12 10:08:33 INFO mapred.JobClient:     Total time spent by all reduces waiting after reserving slots (ms)=0
13/07/12 10:08:33 INFO mapred.JobClient:   Map-Reduce Framework
13/07/12 10:08:33 INFO mapred.JobClient:     Map input records=1
13/07/12 10:08:33 INFO mapred.JobClient:     Map output records=1
13/07/12 10:08:33 INFO mapred.JobClient:     Input split bytes=87
13/07/12 10:08:33 INFO mapred.JobClient:     Spilled Records=0
13/07/12 10:08:33 INFO mapred.JobClient:     CPU time spent (ms)=940
13/07/12 10:08:33 INFO mapred.JobClient:     Physical memory (bytes) snapshot=236580864
13/07/12 10:08:33 INFO mapred.JobClient:     Virtual memory (bytes) snapshot=34998603776
13/07/12 10:08:33 INFO mapred.JobClient:     Total committed heap usage (bytes)=1013252096
13/07/12 10:08:33 INFO mapreduce.ImportJobBase: Transferred 2 bytes in 14.4198 seconds (0.1387 bytes/sec)
13/07/12 10:08:33 INFO mapreduce.ImportJobBase: Retrieved 1 records.

4 Responses to “Connection Resets When Importing from Oracle with Sqoop”

  • Marcin Przepiorowski says:

    I spent some time recently trying to load some data from Oracle into Hadoop
    and I learned that Quest Data Connector for Oracle and Hadoop is working better in terms of spreading load between maps. Did you try it ?

    regards,
    Marcin

  • OracleCommunity says:

    Data Connector for Oracle and Hadoop is the fastest, most scalable way to transfer data between Oracle and Hadoop. This optimized open-source plug-in to Apache Sqoop is more than five times faster than Sqoop alone and significantly reduces database overhead.

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>