温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

sqlldr标准输出未处理导致批处理挂起问题

发布时间:2020-08-10 02:41:32 来源:ITPUB博客 阅读:169 作者:redhouser 栏目:关系型数据库
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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI