sqlldr標準輸出未處理導致批處理掛起問題
1問題
生產環境一個批次處理沒有完成。
2分析
批次處理邏輯:
java->shell->sqlldr
檢查資料庫會話,發現對應會話等待事件為SQL*Net message from client,對應v$session.program為sqlldr@xxx,v$session.seq#保持不變,持續超過5個小時(6:45-12:20)。
查詢資料庫載入的表,發現已載入部分資料,但對應sqlldr日誌為空。
對應sqlldr命令如下:
sqlldr user/pwd data=a.txt control=a.ctl log=a.log bad=a.bad discard=a.dis errors=9999999 rows=1000
在測試環境驗證,sqlldr直接執行時,可以順利載入所有資料;透過java->shell->sqlldr方式執行時,在載入特定行數後停止,問題可以重現。
在進行以上測試時,sqlldr直接執行時,當前視窗會輸出已載入了xx行。其實,問題正出在這裡。透過java->shell->sqlldr方式執行時,標準輸出沒有程式讀取,在要載入的資料量達到一定程度時(超過預設緩衝區大小),就會導致載入過程停止。
驗證過程參考附錄。
3解決方案
處理sqlldr的標準輸出與錯誤輸出,可選方法:
方法一: sqlldr ... silent=(ALL)
方法二: sqlldr .... 1>std.log 2>err.log
附,測試指令碼
--RunShell.java
import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RunShell {
public static void main(String[] args){
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String shpath="/home/oracle/java/test.sh";
System.out.println("---1--" + df.format(new Date()));
Process ps = Runtime.getRuntime().exec(shpath);
System.out.println("---2--" + df.format(new Date()));
//ps.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
String loop = args[0];
System.out.println(loop);
String line;
while ("0".equals(loop) && (line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("---3--" + df.format(new Date()));
ps.waitFor();
System.out.println("---4--" + df.format(new Date()));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
--test.sh
seq -w 1 100000|awk '{print $0"xxxxxxxxxxxxxx"}'
測試1--傳入引數0,主執行緒主動讀取shell的標準輸出
java RunShell 0
---1--2018-04-20 13:23:25
---2--2018-04-20 13:23:25
0
...
...
---3--2018-04-20 13:23:34
---4--2018-04-20 13:23:34
==〉可以順利完成
測試2--傳入引數1,主執行緒不讀取shell的標準輸出
java RunShell 1
---1--2018-04-20 13:28:30
---2--2018-04-20 13:28:30
1
---3--2018-04-20 13:28:30
==〉長時間掛起
Ctrl-C
^C---4--2018-04-20 16:37:08
生產環境一個批次處理沒有完成。
2分析
批次處理邏輯:
java->shell->sqlldr
檢查資料庫會話,發現對應會話等待事件為SQL*Net message from client,對應v$session.program為sqlldr@xxx,v$session.seq#保持不變,持續超過5個小時(6:45-12:20)。
查詢資料庫載入的表,發現已載入部分資料,但對應sqlldr日誌為空。
對應sqlldr命令如下:
sqlldr user/pwd data=a.txt control=a.ctl log=a.log bad=a.bad discard=a.dis errors=9999999 rows=1000
在測試環境驗證,sqlldr直接執行時,可以順利載入所有資料;透過java->shell->sqlldr方式執行時,在載入特定行數後停止,問題可以重現。
在進行以上測試時,sqlldr直接執行時,當前視窗會輸出已載入了xx行。其實,問題正出在這裡。透過java->shell->sqlldr方式執行時,標準輸出沒有程式讀取,在要載入的資料量達到一定程度時(超過預設緩衝區大小),就會導致載入過程停止。
驗證過程參考附錄。
3解決方案
處理sqlldr的標準輸出與錯誤輸出,可選方法:
方法一: sqlldr ... silent=(ALL)
方法二: sqlldr .... 1>std.log 2>err.log
附,測試指令碼
--RunShell.java
import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RunShell {
public static void main(String[] args){
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String shpath="/home/oracle/java/test.sh";
System.out.println("---1--" + df.format(new Date()));
Process ps = Runtime.getRuntime().exec(shpath);
System.out.println("---2--" + df.format(new Date()));
//ps.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
String loop = args[0];
System.out.println(loop);
String line;
while ("0".equals(loop) && (line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("---3--" + df.format(new Date()));
ps.waitFor();
System.out.println("---4--" + df.format(new Date()));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
--test.sh
seq -w 1 100000|awk '{print $0"xxxxxxxxxxxxxx"}'
測試1--傳入引數0,主執行緒主動讀取shell的標準輸出
java RunShell 0
---1--2018-04-20 13:23:25
---2--2018-04-20 13:23:25
0
...
...
---3--2018-04-20 13:23:34
---4--2018-04-20 13:23:34
==〉可以順利完成
測試2--傳入引數1,主執行緒不讀取shell的標準輸出
java RunShell 1
---1--2018-04-20 13:28:30
---2--2018-04-20 13:28:30
1
---3--2018-04-20 13:28:30
==〉長時間掛起
Ctrl-C
^C---4--2018-04-20 16:37:08
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/18922393/viewspace-2153347/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 歸檔日誌滿導致的資料庫掛起故障處理資料庫
- 批處理作業排程問題
- Oracle全部索引丟失導致的效率問題處理Oracle索引
- crontab導致CPU異常的問題分析及處理
- windows批處理之六-echo輸出不換行Windows
- Windows批處理學習(二)——批處理(3)薦Windows
- Windows批處理命令專題Windows
- windows批處理之一:字串處理Windows字串
- 處理若干行輸出的題目
- 使用資料庫處理併發可能導致的問題資料庫
- start_udev導致監聽自動停止問題處理dev
- 歸檔日誌滿導致的資料庫掛起故障處理【轉載】資料庫
- 批處理框架框架
- JDBC 批處理JDBC
- 碎片批處理
- 批處理命令
- 批處理概述
- 執行計劃問題導致處理速度時快時慢的問題
- 傳輸表空間及問題處理
- Windows批處理命令Windows
- 批處理命令大全
- 批處理壓縮
- 批處理----學習
- DOS 批處理命令
- Apache Beam,批處理和流式處理的融合!Apache
- 【RAC】處理因ons導致CPU使用率過高的問題
- linux swap掛載失敗問題處理Linux
- idea外掛報錯導致不能啟動的處理技巧Idea
- OGG複製程式掛起abended處理
- 【問題處理】恢復因誤生成PFILE 導致RAC的SPFILE無效的問題
- Python-OpenCV 處理視訊(一)(二): 輸入輸出 視訊處理PythonOpenCV
- window 批處理檔案
- 什麼是批處理
- 批處理髮郵件
- 批處理檔案命令
- Windows批處理檔案Windows
- bat批處理檔案BAT
- bat 批處理字串操作BAT字串