【问题标题】:Oracle SQLLDR utility no responseOracle SQLLDR 实用程序无响应
【发布时间】:2020-06-25 01:34:07
【问题描述】:

我有一个 java 应用程序,它使用 Oracle SQLLDR 实用程序将 CSV 文件数据上传到 oracle 数据库。

有时,SQLLDR 实用程序不提供 return/response 代码,而我们可以看到 Index 在表中被禁用(这样可以确保调用 SQLLDR 实用程序)并且我在服务器中使用 TOP 命令来查找是否有任何 SQLLDR 进程正在运行,但没有这样的进程。

此外,DBA 确认,数据库上没有与 SQLLDR 操作相关的活动会话。

在 oracle 表级别有什么需要检查的吗? 请让我知道前进的方向。

【问题讨论】:

  • Sqlldr 与 Java 有什么关系?
  • @mentallurg 通过流程构建器关联。这是一段代码,在应用程序中使用,进程不返回响应代码。 code ProcessBuilder pb = new ProcessBuilder(new String[] {"sh", "-c", cmd }); p = pb.start(); p.waitFor(); code
  • 在 Linux 中执行的任何进程都会返回一个 exit codeshell0:成功;any other:失败)。您可以检查exit code 值以确定执行是否失败。还建议手动运行SQLLDR 并查看输出。 IMO 最好记录失败的执行以保持支持/开发工程师的头发到位:-)
  • @TomLime 当我们手动执行它们时,它通过 SQLLDR 实用程序工作。如果我偶尔使用进程构建器通过 java 执行,则不会返回退出代码,并且在数据库端没有运行活动会话。无论如何要检查流程构建器调用的会话/流程是否处于活动状态?
  • @KarthickSambanghi,仅出于调试目的,您可以将&& touch /tmp/was_executed 添加到您的cmd。喜欢:sqlldr ... && touch /tmp/was_executed。这将在成功执行后创建一个/tmp/was_executed 文件(退出代码0)。所以你会知道sqlldr 已正确执行,问题出在其他地方。如果文件没有被创建,这意味着sqlldr 执行失败(退出代码other than 0)。完成调试后不要忘记删除文件创建部分。一旦进程完成执行 - 您将不会通过 top 命令看到它。

标签: java linux oracle sql-loader top-command


【解决方案1】:

SQL

 connect scott/tiger;
 create table employee
(
  id integer,
  name varchar2(10),
  dept varchar2(15),
  salary integer,
  hiredon date
)

控制文件

load data
 infile '/home/db1212/x.txt'
 into table employee
 fields terminated by ","
 ( id, name, dept, salary )

x.txt

200,Jason,Technology,5500
300,Mayla,Technology,7000
400,Nisha,Marketing,9500
500,Randy,Technology,6000
501,Ritu,Accounting,5400

执行

$ sqlldr scott/tiger control=/home/db1212/x.ctl

返回

SQL*Loader: Release 12.1.0.2.0 - Production on Sat Oct 17 21:23:47 2020

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Conventional
Commit point reached - logical record count 5

Table EMPLOYEE:
  5 Rows successfully loaded.

Check the log file:
  x.log
for more information about the load.

执行第二次产生错误

$ sqlldr scott/tiger control=/home/db1212/x.ctl

返回

SQL*Loader: Release 12.1.0.2.0 - Production on Sat Oct 17 21:25:39 2020

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Conventional
SQL*Loader-601: For INSERT option, table must be empty.  Error on table EMPLOYEE

在 SQL*Plus 中截断表

truncate table employee;

从内部使用以下 Java 类

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class t1 {

    public static void main(String[] args) {

        t1 obj = new t1();

        String output = obj.executeCommand();

        System.out.println(output);

    }

    private String executeCommand() {

        StringBuffer output = new StringBuffer();

        try {

            Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "sqlldr scott/tiger control=/home/db1212/x.ctl"});
            p.waitFor();
            BufferedReader reader
                    = new BufferedReader(new InputStreamReader(p.getInputStream()));

            String line = "";
            System.out.println("Return code:"+p.exitValue()+"\n"); 
            while ((line = reader.readLine()) != null) {
                output.append(line + "\n");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return output.toString();

    }

}

构建并运行 t1.java

$ javac t1.java 
$ java t1

返回

Return code:0


SQL*Loader: Release 12.1.0.2.0 - Production on Sat Oct 17 21:30:31 2020

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Conventional
Commit point reached - logical record count 5

Table EMPLOYEE:
5 Rows successfully loaded.

Check the log file:
x.log
for more information about the load.

第二次执行以模仿错误

$ java t1

返回

Return code:1


SQL*Loader: Release 12.1.0.2.0 - Production on Sat Oct 17 21:30:39 2020

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Conventional

再次截断表格

truncate table employee;

并更改输入文件 x.txt

200,Jason,Technology,5500
300,Mayla,Technology,7000
400,Nisha,MarketingAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,9500
500,Randy,Technology,6000
A501,Ritu,Accounting,5400 

给予执行

$ java t1

跟随输出

Return code:2


SQL*Loader: Release 12.1.0.2.0 - Production on Sat Oct 17 21:47:05 2020

Copyright (c) 1982, 2014, Oracle and/or its affiliates.  All rights reserved.

Path used:      Conventional
Commit point reached - logical record count 5

Table EMPLOYEE:
  3 Rows successfully loaded.

Check the log file:
  x.log
for more information about the load.

这意味着:

所以在这种情况下

  • 成功执行 EX_SUCC = 0
  • 一般 SQLLoader 错误,例如“SQLLoader-601:对于 INSERT 选项,表必须为空。表 EMPLOYEE 上的错误”即执行不成功或参数给出 EX_FAIL = 1(Unix,Windows 返回 3 )
  • 成功执行/加载,但出现 SQL 错误,例如“ORA-12899: value too large for column "SCOTT"."EMPLOYEE"."DEPT" (actual: 44, maximum: 15)" 返回 EX_WARN = 2

不幸的是文档状态

SQLLoader 返回除零以外的任何退出代码,您应该查阅系统日志文件和 SQLLoader 日志文件以获取更详细的诊断信息。

这意味着没有办法直接将错误作为标准错误、管道等获取,如果 EX_FAIL 或 EX_WARN,您必须验证写入的日志文件。

【讨论】:

  • 就我而言,我正在尝试每天在已经可用的表上加载数据(增量加载)。偶尔没有从 p.exitValue() 收到返回码,而索引在表上被禁用。这确保了数据加载已经开始,但是 DBA 确认 DB 上没有活动会话,并且顶级进程也没有显示活动会话。但是java进程继续运行。我们如何进一步排除故障?
  • 另外还有一种方法可以检查流程构建器会话是否处于活动状态。
  • 我现在已经尝试过 Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "sqlldr scott/tiger control=/home/ db1212/x.ctl direct=true"});它甚至返回加载返回值的直接路径 - 输出为:返回代码:1 SQL*Loader:版本 12.1.0.2.0 - 2020 年 10 月 19 日星期一 15:17:47 生产 版权所有 (c) 1982、2014、Oracle 和/或其附属公司。版权所有。使用的路径:直接。没有活动会话可能是使用直接路径的结果,因为它使用直接路径 API,这可能不会导致创建附加到客户端的服务器进程。
  • 所以 - 请尝试使用常规路径进行测试。如果将直接路径加载与 SKIP_INDEX_MAINTENANCE=TRUE 结合使用,则需要手动禁用索引。使用手动禁用索引和常规路径应该可以让您查看 DB 和 TOP 中的会话。无论如何 - 没有返回码 - 可以说 - 奇怪。请看这里:stackoverflow.com/questions/56982666/… 我在 Scientific Linux 7.8 (3.10.0-1062.9.1.el7.x86_64) 上使用 java-1.8.0-openjdk-1.8.0.265.b01-1.el7_9.x86_64 即RHEL 7.8 克隆
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
  • 2014-08-16
  • 1970-01-01
  • 2022-07-09
相关资源
最近更新 更多