2013-09-28 2 views
1

sqoop 가져 오기에 이상한 문제가 있습니다. 내가 가져 오기 위해 노력하고있어 데이터는 MySQL을 DB에 다음과 같은 형태 : A1, A2, ..., A8은 VARCHAR 타입과 D1의이다sqoop 자유 형식 쿼리 오류가 발생했습니다.

<a1, a2, a3, d1, a4, a5, a6, a7, a8> 

타임 스탬프 형식입니다. 데이터의 정상화로 인해, 나는 이러한 열을 얻기 위해 여러 테이블을 가입해야했다 - 다음과 같은 것을 :

CREATE OR REPLACE VIEW my_view AS 
SELECT t1.a1, t2.a2....... from table t1 INNER JOIN table t2 ON t1.t2_id = t2.id ........... WHERE <some condition> 

Sqoop을 :

SELECT t1.a1, t2.a2....... from table t1 INNER JOIN table t2 ON t1.t2_id = t2.id ........... WHERE <some condition> 

가 처음에 나는이 같은 전망 시작 명령은 다음과 같이이보기를 사용하여 가져올 수 있습니다.

sqoop import --connect [jdbc url] --username [user] --password [password] --table my_view --target-dir my_dir --split-by a5 --mysql-delimiters --verbose --boundary-query 'SELECT min(a5), max(a5) from t5' 

이 작동합니다. MySQL보기가 원하는만큼 최적화되지 않았기 때문에 원시 SQL을 사용하여 성능 향상 여부를 확인하고자했습니다. 이를 테스트하려면, 내가 대신 자유 형식 쿼리를 사용 :

sqoop import --connect [jdbc url] --username [user] --password [password] --query "SELECT t1.a1, t2.a2....... from table t1 INNER JOIN table t2 ON t1.t2_id = t2.id ............ WHERE <some condition> AND \$CONDITIONS" --target-dir my_dir --split-by a5 --mysql-delimiters --verbose --boundary-query 'SELECT min(a5), max(a5) from t5' 

을 그래서이 경우 --query 매개 변수에 효과적으로 Sqoop을 요구하는 뷰 정의 SELECT 문 플러스 $ 조건이있다. 그러나 이것은 작동하지 않습니다.

13/09/27 20:28:10 INFO mapred.JobClient: Task Id : attempt_201309130032_0122_m_000000_2, Status : FAILED 
java.io.IOException: SQLException in nextKeyValue 
    at org.apache.sqoop.mapreduce.db.DBRecordReader.nextKeyValue(DBRecordReader.java:265) 
    at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:531) 
    at org.apache.hadoop.mapreduce.MapContext.nextKeyValue(MapContext.java:67) 
    at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144) 
    at org.apache.sqoop.mapreduce.AutoProgressMapper.run(AutoProgressMapper.java:64) 
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:764) 
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:364) 
    at org.apache.hadoop.mapred.Child$4.run(Child.java:255) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:396) 
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1190) 
    at org.apache.hadoop.mapred.Child.main(Child.java:249) 
Caused by: java.sql.SQLException: Value 'xxxxxx' can not be represented as  java.sql.Timestamp 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920) 
    at com.mysql.jdbc.ResultSetRow.getTimestampFast(ResultSetRow.java:1102) 
    at com.mysql.jdbc.BufferRow.getTimestampFast(BufferRow.java:576) 
    at com.mysql.jdbc.ResultSetImpl.getTimestampInternal(ResultSetImpl.java:6592) 
    at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:6192) 
    at org.apache.sqoop.lib.JdbcWritableBridge.readTimestamp(JdbcWritableBridge.java:111) 
    at com.cloudera.sqoop.lib.JdbcWritableBridge.readTimestamp(JdbcWritableBridge.java:83) 
    at QueryResult.readFields(QueryResult.java:156) 
    at org.apache.sqoop.mapreduce.db.DBRecordReader.nextKeyValue(DBRecordReader.java:245) 
    ... 11 more 
이 는 지금까지 내가, Sqoop을 타임 스탬프 같은 다른 열 (A3) 값을 해석하려고 말할 수있는 그 변환이 실패로가 단지

이후 : 수입을 절반 기록을 Sqoop을 다음과 같은 이상한 오류와 함께 실패 문자열이며 날짜 유형이 아닙니다. 또한 데이터의 일부가 잘못되었음을 언급해야합니다. 일부 필드에는 개행과 탭이 있지만 날짜 필드에는 유효한 값이 있습니다. 심지어 MySQL에서 REPLACE 함수를 사용하여 이러한 데이터를 제거하려고했지만 그것은 쓸모가 없다.

데이터가 동일하고 두 경우 모두 동일한 SELECT 문이 사용되는 경우 동일한 결과 (예 : SELECT에서 반환 한 레코드 수와 HDFS로 가져 오는 레코드 수)가 같을 것으로 예상했습니다.

이전에이 동작을 본 사람이 있습니까? 이 문제를 어떻게 해결할 수 있는지에 대한 아이디어가 있습니까?

+0

에 대한이 작품? 당신은 대답으로 그것을 제공해야하고, 당신 자신의 대답을 받아 들여야합니다. (http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/). 이렇게하면 질문이 해결 된 것으로 표시됩니다. – Freerobots

+0

나는 내 자신의 질문에 대답 할 수 있다는 것을 몰랐다. 포인터 주셔서 감사. – srikrishna

답변

5
내가 다른 MySQL의 드라이버 버전과 같은 명령을 실행하려고

- 같은 오류가 모든 경우에 무슨 일이 벌어지고있는 동안, 메시지가이 시간을 좀 더 분명했다 :

13/10/21 22:19:18 INFO mapred.JobClient: Task Id : attempt_201309130032_0308_m_000000_0, Status : FAILED 
java.io.IOException: SQLException in nextKeyValue 
    at org.apache.sqoop.mapreduce.db.DBRecordReader.nextKeyValue(DBRecordReader.java:265) 
    at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:531) 
    at org.apache.hadoop.mapreduce.MapContext.nextKeyValue(MapContext.java:67) 
    at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144) 
    at org.apache.sqoop.mapreduce.AutoProgressMapper.run(AutoProgressMapper.java:64) 
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:764) 
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:364) 
    at org.apache.hadoop.mapred.Child$4.run(Child.java:255) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at javax.security.auth.Subject.doAs(Subject.java:396) 
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1190) 
    at org.apache.hadoop.mapred.Child.main(Child.java:249) 
Caused by: java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column 7 to TIMESTAMP. 
    at com.mysql.jdbc.ResultSet.getTimestampFromBytes(ResultSet.java:6886) 
    at com.mysql.jdbc.ResultSet.getTimestampInternal(ResultSet.java:6921) 
    at com.mysql.jdbc.ResultSet.getTimestamp(ResultSet.java:6245) 
    at org.apache.sqoop.lib.JdbcWritableBridge.readTimestamp(JdbcWritableBridge.java:111) 
    at com.cloudera.sqoop.lib.JdbcWritableBridge.readTimestamp(JdbcWritableBridge.java:83) 
    at QueryResult.readFields(QueryResult.java:156) 
    at org.apache.sqoop.mapreduce.db 

그래서 기본적인 문제는 그 '0000-00-00 00:00:00'날짜의 값은 db에 저장되어 있지만 드라이버에 의해 처리 될 수 없습니다 (여러 버전을 시도했지만 그 중 아무 것도 작동하지 않음). sqoop에서 자유 형식 쿼리 옵션을 가진 원시 sql을 사용할 때 드라이버는이 날짜를 위의 오류로 끝나는 날짜 객체로 변환하려고 시도합니다. 보기를 사용하여 동일한 날짜 값을 추출한 경우에는이 오류가 발생하지 않습니다. 드라이버가이 값을이 경우 날짜 객체로 변환하려고 시도하지 않는 것처럼 보입니다. 어떤 이유로 든 MySQL 드라이버와 서버는 잘못된 날짜를 처리하기 위해 동기화되지 않은 것처럼 보입니다. MySQL docs에서

:

As of 5.0.2, the server requires that month and day values be legal, and not merely in the range 1 to 12 and 1 to 31, respectively. With strict mode disabled, invalid dates such as '2004-04-31' are converted to '0000-00-00' and a warning is generated. With strict mode enabled, invalid dates generate an error. 

우리의 기존 DB 서버가 엄격 모드가 비활성화 한 및 레거시 응용 프로그램 (예 : '2004-04-31'와 같은) 잘못된 날짜를 삽입하려고 할 때마다, 그것은 0000 '로 변환됩니다 -00-00 '그리고 이것은 원시 sql 경우에 대해 위에서 언급 한 것처럼 드라이버가 처리 할 수 ​​없습니다.이러한 레코드가 where 절의 필터로 제거되면 sqoop 가져 오기가 예상대로 작동합니다.

0

당신은 당신의 Sqoop을 명령에

JDBC를이 JDBC URL을 사용할 수있다 : mysql : // yourserver를 : 3306/yourdatabase zeroDateTimeBehavior = convertToNull

당신이 당신의 자신의 질문에 대답 나

관련 문제