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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用資料庫處理併發可能導致的問題資料庫
- 處理若干行輸出的題目
- 批處理概述
- linux swap掛載失敗問題處理Linux
- Apache Beam,批處理和流式處理的融合!Apache
- SpringBatch基本的批處理指導原則SpringBAT
- Oracle 12c因bug導致ORA-04031問題處理過程Oracle
- [git] git問題處理Git
- golang json處理問題GolangJSON
- 自然語言處理之序列標註問題自然語言處理
- iOS --NSDecimalNumber 處理計算精度不準確問題iOSDecimal
- Spring Batch 基本的批處理指導原則SpringBAT
- bat 批處理字串操作BAT字串
- Dynamics CRM 2013 批處理
- window 批處理檔案
- 什麼是批處理
- ECharts圖座標軸文字換行問題處理Echarts
- Ubuntu處理依賴問題Ubuntu
- 資料處理--pandas問題
- 處理SQLServer errorlog滿問題SQLServerError
- 併發問題處理方式
- Linux 問題處理集錦Linux
- pat處理輸入輸出小技巧(待更新)
- 如何處理快取導致的無效曝光快取
- jenkins導致硬碟佔用滿了如何處理Jenkins硬碟
- 帶你認識FusionInsight Flink:既能批處理,又能流處理
- DevExpress 的LayoutControl控制元件導致資源無法釋放的問題處理devExpress控制元件
- 關於Cordova框架對URL攔截導致通訊丟失問題的處理框架
- 【問題處理】MySQL忘記root密碼的處理辦法MySql密碼
- Python批處理:檔案操作Python
- MPP架構和批處理架構
- bat批處理常用指令碼BAT指令碼
- java當中的批處理Java
- JDBC當中的批處理JDBC
- 批處理命令之tree命令
- 簡單實現批處理
- 特徵預處理之歸一化&標準化特徵
- Jenkins執行遠端Windows批處理的許可權問題JenkinsWindows