2013-03-06 63 views
1

據我瞭解,我正在編寫一個使用Hadoop的Java應用程序,它使用Log4j。在我的應用程序中,Log4J工作正常。我正在使用JDBCAppender來寫入Oracle數據庫。發生什麼事是因爲我正在運行應用程序,所以在log4j調用過程中,它在Hadoop jar中崩潰並給出一個缺少的逗號錯誤。這很奇怪,因爲它在我的程序中起作用,但在Hadoop中崩潰。我打開了log4j中的調試,一切都看起來很正常。Log4J引用Jar中的JDBC SQL錯誤

我的問題如下。 1)是否有可能在JDBCAppender中打開額外的日誌記錄來查看哪些SQL語句是有問題的? 2)我應該怎麼處理這個問題! :)

這裏是異常和log4j.properties文件。

log4j:ERROR Failed to excute sql 
java.sql.SQLSyntaxErrorException: ORA-00917: missing comma 

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447) 
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) 
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879) 
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:505) 
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:223) 
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) 
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:193) 
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1033) 
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1328) 
at oracle.jdbc.driver.OracleStatement.executeUpdateInternal(OracleStatement.java:1837) 
at oracle.jdbc.driver.OracleStatement.executeUpdate(OracleStatement.java:1802) 
at   oracle.jdbc.driver.OracleStatementWrapper.executeUpdate(OracleStatementWrapper.java:294) 
at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:218) 
at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:289) 
at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:186) 
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251) 
at  org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66) 
at org.apache.log4j.Category.callAppenders(Category.java:206) 
at org.apache.log4j.Category.forcedLog(Category.java:391) 
at org.apache.log4j.Category.log(Category.java:856) 
at org.apache.commons.logging.impl.Log4JLogger.info(Log4JLogger.java:199) 
at  org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter.commitTask(FileOutputCommitter.java:173) 
at org.apache.hadoop.mapred.Task.commit(Task.java:1012) 
at org.apache.hadoop.mapred.Task.done(Task.java:882) 
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:374) 
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:212) 
I/O error: Read timed out 

而且屬性文件...

log4j.rootLogger=INFO, DB 

log4j.appender.DB = org.apache.log4j.jdbc.JDBCAppender 

log4j.appender.DB.URL = jdbc:oracle:thin:@//192.168.0.18:1521/dev01.home.net 
log4j.appender.DB.driver = oracle.jdbc.OracleDriver 
log4j.appender.DB.user = syslog 
log4j.appender.DB.password = syslog 
log4j.appender.DB.sql = INSERT INTO SERVICELOG values (log4net_seq.nextVal, sysdate, '%p', null, '%m','') 
log4j.appender.DB.layout = org.apache.log4j.PatternLayout 

編輯0

其實,我覺得我可能將要發生什麼。試圖打印的字符串中有一個單引號。對於Oracle來說,這是一個不容否認的特性。現在我只需要弄清楚如何刪除它:)。

/EDIT 0

+0

I/O錯誤似乎在哪裏發生?它是數據庫連接嗎? – asgs 2013-03-06 17:48:19

+1

我認爲底部的I/O錯誤是不相關的。對於那個很抱歉。即使一切運行良好,我都能得到它。 – 2013-03-06 18:00:48

回答

2

我明白了。 Hadoop在他們的日誌中有單引號,這是對Oracle的寫操作。我實現了一個hack和修改後的log4j去除單引號。更改是在強制日誌函數的Category.java中。我檢查傳入的對象是否是String的一個instanceof。然後,我拿起那個字符串並對它執行replaceAll(「'」,「」)。我可以做一個replaceAll(「'」,「''」)來使單引號適合Oracle,但對我來說並不重要。

+0

你也可以嘗試這個項目http://www.dankomannhaupt.de/projects/index.html – Leo 2014-11-25 01:56:06

+0

或者你可以嘗試這樣的事情(使用oracle引用) - appender.setSql(「INSERT INTO LOGS(ID,DATED ,LOGGER,LOGLEVEL,MESSAGE)VALUES(logs_seq.nextval,sysdate,'%C','%p',q'[%m]')「); – Leo 2014-11-25 12:48:18

0

1: 您可以非常容易地定義你的happender的日誌級別: log4j.appender.DB = DEBUG
你甚至可以將日誌級別設置爲特定的軟件包這樣com.foobar = DEBUG

2您可能在log4j上存在版本衝突。最簡單的方法可能是使用與Hadoop使用的版本完全相同的版本。其他人可能會切換到您的應用程序的另一個記錄器實施,如logback。

最後一個是排除hadoop的log4j傳遞依賴項,如果兩個項目都使用maven但對結果沒有保證。