惊呆,Oracle的这个坑竟然让我踩上了

简介: 惊呆,Oracle的这个坑竟然让我踩上了

今天,系统中的一个业务处理莫名地执行了6个小时都没有结束,正常处理也就是3分钟左右,对原因进行定位,发现是在Oracle客户端上同步执行一个命令没有响应。今天来分享一下这个问题,让更多的人避开这个坑。

1 业务场景

我们要把一个csv文件(文件名biz.csv)中的数据读取到Oracle数据库表(表名t_biz,t_biz)中,数据库表t_biz表结构如下:

字段名称 字段类型 字段描述
id NUMBER(11) 唯一标识
a VARCHAR(10) 业务a
b VARCHAR(10) 业务b
c VARCHAR(10) 业务c

biz.csv文件内容如下:

id,a,b,c
1,a1,b1,c1
2,a2,b2,c2
3,a3,b3,c3

把biz.csv文件的内容读入到表t_biz,为了提高效率,这里使用了sqlldr 命令,命令如下:

sqlldr test/test123@biz control=/home/jinjunzhu/biz/T_BIZ.ctl log=/home/jinjunzhu/biz/T_BIZ.log bad=/home/jinjunzhu/biz/T_BIZ.bad

解释一下这个命令,test/test123 是要访问的数据库实例的用户名/密码,biz 是数据库实例名称。T_BIZ.ctl是控制文件,内容如下:

options(skip=1,rows=10000,errors=0,parallel=true,bindsize=1048576,readsize=1048576)
load data 
infile '/home/jinjunzhu/biz/biz.csv'
fields terminated by ','
truncate into table day_data
trailing nullcols
(id,a,b,c)

业务代码中调用这个命令,代码如下:

private int execute(String cmd) throws Exception{
    Process process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
    process.waitFor(10, TimeUnit.SECONDS);
    Integer status = process.waitFor();
    return status == null ? -1 : status;
}

2 问题现场

程序执行到上面第4行的时候,程序hang住了,一直没有返回。这个代码之前从来没有出过问题,最近也没有上过线,今天唯一的不同就是文件数据量越来越大,今天比昨天大了几万行。

数据库情况:

  • 看不到有sqlldr命令等待的情况
  • CPU正常
  • 手工执行上面命令可以成功,但是打印的日志非常多,如下图:

微信图片_20221212211111.jpg

3 原因分析

网上搜这个问题竟然很多,原因有下面三类:

3.1 Oracle版本低

Oracle版本低,建议升级到10.2.0.2或以上,这个方案忽略,因为我们的数据库版本是Oracle 11.2.0.4.0。

3.2 数据落库情况

本以为sqlldr命令执行失败了,但是文件数据已经全部落到t_biz表。这说明命令执行成功了,只是Oracle没有给应用返回结果。难道是Oracle数据库hang住了?但是上面的问题现场已经确认,Oracle并没有hang在sqlldr这个命令上。

3.3 最终答案

看了好多博客,最后发现竟然不是Oracle的原因。根本原因是使用java执行shell时,如果不读取标准输出,这个输出就会输出到缺省缓冲区,如果输出流太大,必将打满缓冲区,导致程序hang住。

从上面问题现场的手工执行中可以看到,因为加载的数据量很大大,结果输出也流非常大,这很容易超出缺省缓冲区大小。

4 解决方案

问题已经很明确了,解决方案也就有了,处理sqlldr的输出就可以解决。解决方法有下面三种。

4.1 增加参数

在sqlldr命令后面增加一个参数,silent=(ALL),最后命令如下:

sqlldr test/test123@biz control=/home/jinjunzhu/biz/T_BIZ.ctl log=/home/jinjunzhu/biz/T_BIZ.log bad=/home/jinjunzhu/biz/T_BIZ.bad silent=(ALL)

4.2 程序读取标准输出

程序中读取sqlldr命令返回的输出,修改后的代码如下:

private int execute(String cmd) throws Exception{
    Process process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
    process.waitFor(10, TimeUnit.SECONDS);
    Integer status;
    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
    return (status = process.waitFor()) == null ? -1 : status;
}

4.3 文件接收标准输出

可以在sqlldr命令中增加文件参数来接收命令的标准输出,最后我采用了这种方式,命令如下:

sqlldr test/test123@biz control=/home/jinjunzhu/biz/T_BIZ.ctl log=/home/jinjunzhu/biz/T_BIZ.log bad=/home/jinjunzhu/biz/T_BIZ.bad 1>/home/jinjunzhu/biz/std.log 2>/home/jinjunzhu/biz/err.log

5 总结

这个问题刚出现的时候,一直以为是Oracle的问题,但是后来研究发现,这个锅真的不能让Oracle来背。关于sqlldr命令的详细参数介绍,已经比较成熟,大家可以自行网络查找。

相关文章
|
SQL XML Oracle
惊呆,一条sql竟然让oracle奔溃了
惊呆,一条sql竟然让oracle奔溃了
202 0
惊呆,一条sql竟然让oracle奔溃了
|
2月前
|
存储 Oracle 关系型数据库
Oracle数据库的应用场景有哪些?
【10月更文挑战第15天】Oracle数据库的应用场景有哪些?
200 64
|
4月前
|
存储 自然语言处理 Oracle
Oracle数据库字符集概述及修改方式
【8月更文挑战第15天】Oracle 数据库字符集定义了数据的编码方案,决定可存储的字符类型及其表示方式。主要作用包括数据存储、检索及跨系统传输时的正确表示。常见字符集如 AL32UTF8 支持多语言,而 WE8MSWIN1252 主用于西欧语言。修改字符集风险高,可能导致数据问题,需事先备份并评估兼容性。可通过 ALTER DATABASE 语句直接修改或采用导出-导入数据的方式进行。完成后应验证数据完整性。此操作复杂,须谨慎处理。
119 5
|
17天前
|
存储 Oracle 关系型数据库
数据库数据恢复—ORACLE常见故障的数据恢复方案
Oracle数据库常见故障表现: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE ASM存储破坏。 3、ORACLE数据文件丢失。 4、ORACLE数据文件部分损坏。 5、ORACLE DUMP文件损坏。
64 11
|
4月前
|
数据采集 Oracle 关系型数据库
实时计算 Flink版产品使用问题之怎么实现从Oracle数据库读取多个表并将数据写入到Iceberg表
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
1月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
1月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
23天前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。
|
1月前
|
SQL Oracle 关系型数据库
Oracle数据库优化方法
【10月更文挑战第25天】Oracle数据库优化方法
54 7
|
2月前
|
存储 Oracle 关系型数据库
数据库数据恢复—Oracle ASM磁盘组故障数据恢复案例
Oracle数据库数据恢复环境&故障: Oracle ASM磁盘组由4块磁盘组成。Oracle ASM磁盘组掉线 ,ASM实例不能mount。 Oracle数据库故障分析&恢复方案: 数据库数据恢复工程师对组成ASM磁盘组的磁盘进行分析。对ASM元数据进行分析发现ASM存储元数据损坏,导致磁盘组无法挂载。

推荐镜像

更多