`
cuisuqiang
  • 浏览: 3960435 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
3feb66c0-2fb6-35ff-968a-5f5ec10ada43
Java研发技术指南
浏览量:3670224
社区版块
存档分类
最新评论

Oracle JDBC 连接时的一个BUG

阅读更多

前两天接到一个工作,某网站无法访问了,重启后也一直挂在哪里,起不来。

我刚开始怀疑是程序配置问题,后来发现,只要初始化Spring内容服务就起不来。看了一下spring配置文件里面配置了两个数据源,都是由tomcat管理的jndi数据源。查看了一下发现有一个数据源有问题,使用小程序测试,发现无法连接该数据库,同时也发现一个问题,程序一直挂在哪里,是否能连接却不再返回结果。

 

网上也有人遇到过这类问题,看来都没有很好的解决方案,当然,我也没有。

我现在只是说明一下问题,并复现一下场景。

你可以使用附件内调试工具或自己下载一个TCP调试工具,然后开启一个端口,然后写一个小程序把这个端口当成Oracle服务端口去访问。

 

 

package com;
import java.sql.Connection;
import java.util.Properties;
import oracle.jdbc.driver.OracleDriver;
/**
 * 数据库连接对象管理类
 * @说明
 * @author cuisuqiang
 * @version 1.0
 * @since
 */
public class ConnectionManager {
	private static final String url = "jdbc:oracle:thin:@192.168.1.155:1521:orcl";
	private static final String username = "scott";
	private static final String userpass = "bi123";
	public static void main(String[] args) throws Exception {
		Connection conn = getConnection("1");
		if (null != conn) {
			System.out.println(conn.toString());
		} else {
			System.out.println("NO LINK");
		}
	}
	public static Connection getConnection(String tar) {
		Connection conn = null;
		try {
			OracleDriver driver = new OracleDriver();
			Properties properties = new Properties();
			properties.put("user", username);
			properties.put("password", userpass);
			conn = driver.connect(url, properties);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
}

 

看服务窗口:

 

可以看到,程序发来了登录信息,但是我们不回复,然后就会看到,程序死在了:

conn = driver.connect(url, properties);

 获得连接这里!

 

请您到ITEYE看我的原创:http://cuisuqiang.iteye.com

或支持我的个人博客,地址:http://www.javacui.com

 

4
4
分享到:
评论
33 楼 cuisuqiang 2013-01-15  
yuechen323 写道
写法太另类了,我就不信你用规范的写法会出现这个问题,我干oracle5,6年了,9,10,11全用过,你这个问题还没遇到过
如果你说的官方推荐的这个写法,那当我没说吧~

请您参照我的场景,写个例子试试!如果还是没遇到,当我什么都没说吧!另外,你说的规范,我也希望自己换个写法就能通了!如果您认为写法有问题,请参照现在Oralce官方的Demo,下载一个看看他们的代码怎么写的!
32 楼 yuechen323 2013-01-15  
写法太另类了,我就不信你用规范的写法会出现这个问题,我干oracle5,6年了,9,10,11全用过,你这个问题还没遇到过
如果你说的官方推荐的这个写法,那当我没说吧~
31 楼 cuisuqiang 2013-01-15  
rensanning 写道
properties.put("oracle.jdbc.ReadTimeout", "10000"); 
properties.put("oracle.net.CONNECT_TIMEOUT", "10000"); 

经测试,无效果!
30 楼 masuweng 2013-01-15  
学习了!!!
29 楼 rensanning 2013-01-15  
properties.put("oracle.jdbc.ReadTimeout", "10000"); 
properties.put("oracle.net.CONNECT_TIMEOUT", "10000"); 
28 楼 huaye2007 2013-01-15  
http://blog.csdn.net/downloadsunlight2009/article/details/7579058
在jdbc的标准接口中,有DriverManager.setLoginTimeout方法,用来设置建立数据库连接的超时.我在对sql   server进行过测试,该方法是能够生效的.但是如果对于oracle(8i,9i),该方法没有效果.查阅oracle的官方文档,结果竟然是 "Oracle   JDBC   does   not   support   login   timeouts.   Calling   the   static   DriverManager.setLoginTimeout()   method   will   have   no   effect ",没有想到oralce   jdbc   driver竟然没有实现这个功能,
27 楼 xurichusheng 2013-01-15  
Oracle驱动发出登录消息后就一直死等,这样的情况,我能想到的原因有:
1. 由于某种原因,oracle被锁住了,或者说,oracle拒绝了访问,可能是oracle的锁机制造成的;
2. 多线程下的同步问题;
3. oracle的某个服务由于某种原因被停止了;

在调试多线程的时候,经常会遇到这样的问题
debug的时候,就死在某行代码下,再也运行不了了,
当前线程变成了守护线程,死锁了
这个时候程序是不会报异常的,你得把所有相关的类、方法全都调试
而且有可能是你调试1天都找不到原因
这种让人抓狂的问题,得是对线程或者说对java相关API类有深入了解的人才能解决
26 楼 cuisuqiang 2013-01-15  
看来大家看惯了:
Class.forName(driver);
conn = DriverManager.getConnection(url, username, userpass);

,我这么写就有点水土不服了:
OracleDriver driver = new OracleDriver();
Properties properties = new Properties();
properties.put("user", username);
properties.put("password", userpass);
conn = driver.connect(url, properties);

首先肯定的说,不是写法问题!

其次,程序一直运行,突然出问题,我也是从各个角度排查后才发现电信方面数据库的问题!可能是我太相信他们了!

其次,说到解决问题,问题已经解决。但是Oracle驱动发出登录消息后就一直死等,这种做法是否欠妥?
25 楼 cuisuqiang 2013-01-15  
xurichusheng 写道
如果老是纠结于一个问题,又找不出原因,也不从另外的角度查找问题
如果我是你的PM,我会认为你解决问题的能力不行

我已经解决问题了,我让跑腿的跑到电信机房,让他们领导签字把服务器重启了!然后就好了,如果这点问题就解决不了,那PM就不用认为了,这个人可以走人了!不过我现在不是说怎么解决问题,我说的是Oracle的驱动如此处理,应该是一个问题!做通信的,连接能不能用,登录能不能成功,总的有个提示,而不是堵死!假如你登录ITEYE,网页可以打开但是登录却一直提示登录中,你什么感受?
24 楼 xurichusheng 2013-01-15  
之前我也遇到过这样的一个问题,框架用的是struts2+hibernate,在客户的测试环境上运行完全没问题,但是一放到正式环境上,就会报错说不支持批量操作
当时首先想到的是正式环境有问题,但是客户可不是这么想的,他就认为你的程序有问题
这时候可不能纠结于环境问题,然后上网查资料,换了jdbc包,但是还是没用
最后能想到的最后一个办法就是sql的问题
既然Hibernate不行,我就全改成了JDBC,最后问题解决了
所以,从多个角度去考虑问题,这样才能更快的解决问题。

特别是如果是在现网(如:移动、联通、电信),你老是说TCP连接不上,也不从代码或者其他的角度去逐个排除,那你肯定会被客户投诉
23 楼 xurichusheng 2013-01-15  
如果老是纠结于一个问题,又找不出原因,也不从另外的角度查找问题
如果我是你的PM,我会认为你解决问题的能力不行
22 楼 xurichusheng 2013-01-15  
说错了,应该是“魔力猫咪”的说法
21 楼 xurichusheng 2013-01-15  
LZ,你可以用
    Class.forName(driver); 
    conn = DriverManager.getConnection(url, username, userpass); 
试试嘛
如果老是陷在TCP连接上,又找不出问题
这时候,可以考虑 cuisuqiang 的说法,确定没问题
那可以从代码入手呀
20 楼 cuisuqiang 2013-01-15  
魔力猫咪 写道
cuisuqiang 写道
魔力猫咪 写道
cuisuqiang 写道
魔力猫咪 写道
首先应用服务器可以Ping通数据库服务器吗?数据库服务器本身服务是否正常?别的机器可以访问不?首先要排除网络和数据库本身的问题。

我说的问题是,该端口可用,但是发送登录连接后不给回应,就会造成挂起的现象


我只问一个,数据库服务器能否正常提供访问。其他的计算机能否连接到数据库。你查什么TCP的都是找错了方向。首先应该确认的就是数据库服务器是否可用。端口可以连接,表示数据库服务器的监听是启动的。但是数据库服务器本身是否正常则是另一个问题。最简单的办法,你在自己机器上面用sqlplus连接数据库。能连接就表示是应用服务器到数据库服务器之间的网络有问题,或者应用服务器上面的代码配置有问题。不能连接,就直接去数据库服务器上面看其数据库应用是否正常。应用正常,查网络。应用不正常,看数据库错误日志。
这里不要纠结于什么JDBC。如果系统之前没有修改,那么代码和配置出问题的可能性很小。因为这个系统你们以前应该是正常服务的。如果最近有修改,最简单的测试办法就是回退到上一个版本。
简单的排除都没做,非要死扣TCP端口。

谢谢你的分析!从解决问题的角度是应该这么做,不过从技术角度来说,Oracle使用TCP进行连接且进行登录操作,TCP连接是可以的,登录无响应却没有超时时间,才造成了服务挂起!

那么数据库那边到底是否正常呢。你TCP可以连接,只能说明Oracle的数据库监听进程在工作,其他的都不能确定。结果是到现在我也没看到你排除了数据库本身和网络的原因(能ping通能有TCP连接并不表示网络完全没有问题,比如网络有可能过慢、不稳定、丢包等等)。如果排除了这些问题,我觉得你这种情况9成以上应该解决了。你现在的说法我认为是在说Oracle的JDBC驱动本身有问题,而这个可能性实在太小。如果你真的怀疑,可以在排除了其他可能之后,更换不同版本的JDBC驱动进行测试并要求Oracle的技术支持。

可能是我没有表达清楚!你看我的问题再现的环境就知道,确实你是说的那种监听在但是无法处理请求包括登录请求!也就是说OracleDriver 通过TCP发送了登录请求后,没有任何响应的情况下,他会堵塞!但是实际许多情况下,即使没有响应,也应该超时处理的!
19 楼 cuisuqiang 2013-01-15  
alvin198761 写道
你这个写法没问题就是见鬼了,实例化那么都去多,每个驱动只是创建了一个连接,
最郁闷的是我还没有看到关闭,
Class.forName(driver);  
conn = DriverManager.getConnection(url, username, userpass); 
这才是jdbc……

请看官方示例和JDK底层实现!确实没有关闭,谢谢提醒!
18 楼 alvin198761 2013-01-15  
你这个写法没问题就是见鬼了,实例化那么都去多,每个驱动只是创建了一个连接,
最郁闷的是我还没有看到关闭,
Class.forName(driver);  
conn = DriverManager.getConnection(url, username, userpass); 
这才是jdbc……
17 楼 魔力猫咪 2013-01-15  
cuisuqiang 写道
魔力猫咪 写道
cuisuqiang 写道
魔力猫咪 写道
首先应用服务器可以Ping通数据库服务器吗?数据库服务器本身服务是否正常?别的机器可以访问不?首先要排除网络和数据库本身的问题。

我说的问题是,该端口可用,但是发送登录连接后不给回应,就会造成挂起的现象


我只问一个,数据库服务器能否正常提供访问。其他的计算机能否连接到数据库。你查什么TCP的都是找错了方向。首先应该确认的就是数据库服务器是否可用。端口可以连接,表示数据库服务器的监听是启动的。但是数据库服务器本身是否正常则是另一个问题。最简单的办法,你在自己机器上面用sqlplus连接数据库。能连接就表示是应用服务器到数据库服务器之间的网络有问题,或者应用服务器上面的代码配置有问题。不能连接,就直接去数据库服务器上面看其数据库应用是否正常。应用正常,查网络。应用不正常,看数据库错误日志。
这里不要纠结于什么JDBC。如果系统之前没有修改,那么代码和配置出问题的可能性很小。因为这个系统你们以前应该是正常服务的。如果最近有修改,最简单的测试办法就是回退到上一个版本。
简单的排除都没做,非要死扣TCP端口。

谢谢你的分析!从解决问题的角度是应该这么做,不过从技术角度来说,Oracle使用TCP进行连接且进行登录操作,TCP连接是可以的,登录无响应却没有超时时间,才造成了服务挂起!

那么数据库那边到底是否正常呢。你TCP可以连接,只能说明Oracle的数据库监听进程在工作,其他的都不能确定。结果是到现在我也没看到你排除了数据库本身和网络的原因(能ping通能有TCP连接并不表示网络完全没有问题,比如网络有可能过慢、不稳定、丢包等等)。如果排除了这些问题,我觉得你这种情况9成以上应该解决了。你现在的说法我认为是在说Oracle的JDBC驱动本身有问题,而这个可能性实在太小。如果你真的怀疑,可以在排除了其他可能之后,更换不同版本的JDBC驱动进行测试并要求Oracle的技术支持。
16 楼 cuisuqiang 2013-01-15  
HeDYn 写道
我在jre7下(或者jre6u29以上)用jdbc连接sql server 时也会出现连不上的现象,在建立连接之前加上
System.setProperty("java.net.preferIPv4Stack", "true");

试试吧

谢谢,不过,没有效果!
15 楼 cuisuqiang 2013-01-15  
魔力猫咪 写道
cuisuqiang 写道
魔力猫咪 写道
首先应用服务器可以Ping通数据库服务器吗?数据库服务器本身服务是否正常?别的机器可以访问不?首先要排除网络和数据库本身的问题。

我说的问题是,该端口可用,但是发送登录连接后不给回应,就会造成挂起的现象


我只问一个,数据库服务器能否正常提供访问。其他的计算机能否连接到数据库。你查什么TCP的都是找错了方向。首先应该确认的就是数据库服务器是否可用。端口可以连接,表示数据库服务器的监听是启动的。但是数据库服务器本身是否正常则是另一个问题。最简单的办法,你在自己机器上面用sqlplus连接数据库。能连接就表示是应用服务器到数据库服务器之间的网络有问题,或者应用服务器上面的代码配置有问题。不能连接,就直接去数据库服务器上面看其数据库应用是否正常。应用正常,查网络。应用不正常,看数据库错误日志。
这里不要纠结于什么JDBC。如果系统之前没有修改,那么代码和配置出问题的可能性很小。因为这个系统你们以前应该是正常服务的。如果最近有修改,最简单的测试办法就是回退到上一个版本。
简单的排除都没做,非要死扣TCP端口。

谢谢你的分析!从解决问题的角度是应该这么做,不过从技术角度来说,Oracle使用TCP进行连接且进行登录操作,TCP连接是可以的,登录无响应却没有超时时间,才造成了服务挂起!
14 楼 HeDYn 2013-01-15  
我在jre7下(或者jre6u29以上)用jdbc连接sql server 时也会出现连不上的现象,在建立连接之前加上
System.setProperty("java.net.preferIPv4Stack", "true");

试试吧

相关推荐

    Oracle JDBC驱动11.2.0.4

    在11g Release 2版本中,11.2.0.4是一个重要的维护版本,包含了一些性能优化、bug修复和新特性。 1. **JDBC驱动类型**: Oracle JDBC驱动主要有四种类型: - ** Thin Driver**: 这是一个轻量级的纯Java驱动,无需...

    mysqljdbc.jar;oraclejdbc.jar

    oraclejdbc.jar”提到了两个重要的Java数据库连接驱动,分别是MySQL的JDBC驱动和Oracle的JDBC驱动。JDBC(Java Database Connectivity)是Java中用于与各种数据库进行交互的一种标准接口,它允许Java程序通过Java ...

    Oracle JDBC Drivers release 11.2.0.3.0.rar

    remote Oracle databases. - JDBC Server-side Internal Driver 11R2 Server-side JDBC driver for use by Java Stored procedures. This driver used to be called the "JDBC Kprb Driver".

    Oracle jdbc for 11g 最新版 驱动 ojdbc6.jar

    从9.0.1开始的每个release都推荐使用oracle.jdbc。这一天终于到来,在11g中,引用oracle.jdbc.driver不再通过编译。  3.j2se 1.2,1.3,1.4不再支持。11R1不再包括这些版本的jar和zip,如果仍然使用这些版本,可以...

    Oracle jdbc for 11g 最新版 驱动 ojdbc6dms.jar

    从9.0.1开始的每个release都推荐使用oracle.jdbc。这一天终于到来,在11g中,引用oracle.jdbc.driver不再通过编译。  3.j2se 1.2,1.3,1.4不再支持。11R1不再包括这些版本的jar和zip,如果仍然使用这些版本,可以...

    Oracle11 的ojdbc 去除了bug

    1. ojdbc6_g.jar:这是一个包含调试信息的ojdbc6驱动版本,"g"代表"debug",它对于开发者追踪和调试驱动中的问题非常有用。 2. ojdbc5_g.jar:同样,这个是ojdbc5驱动的调试版本,适用于JDK 5.0。 3. ojdbc6.jar:这...

    Oracle 11.1.0.7.0 JDBC 包

    Oracle11.1.0.7.0 驱动包。完全解决Oracle11驱动BUG,包含 ojdbc5.zip,ojdbc5_g.zip,ojdbc6.zip,ojdbc6_g.zip只要将4个包覆盖\11.1.0\db_1\jdbc\lib下,就OK。亲测

    连接Oracle数据库所需jar包

    其中,Thin Driver是最常用的一种,它是一个纯Java实现的驱动,不需要Oracle客户端软件,可以直接与数据库服务器通信,适用于跨平台的网络环境。 2. **ojdbc5、ojdbc6和ojdbc14**: - **ojdbc5.jar**: 这个版本的...

    达梦数据库连接方式及jdbc驱动包.rar

    使用的是达梦7,这个数据库有很多BUG,官方提供的客户端,不仅卡,而且登录了后,使用Java JDBC操作更新时,是会被阻塞的,所以,在使用Java开发达梦应用时候,尽量关闭他客户端。 另外达梦还有个模式的概念,这...

    JDBC连接数据库mysql驱动

    在Java中,连接到MySQL通常需要引入一个名为"mysql-connector-java"的JAR包,这个包包含了驱动程序,使得Java应用程序能够识别并通信MySQL服务器。 描述中提到的"用于java连接mysql数据库的jar包"正是指的这个...

    jdbc针对不同数据库的连接方式demo.rar

    2. 连接URL:格式为"jdbc:oracle:thin:@[hostname]:[port]:[service_name]",例如:"jdbc:oracle:thin:@localhost:1521/XE"。 3. 示例代码: ```java Class.forName("oracle.jdbc.driver.OracleDriver"); Connection...

    oracle各java连接驱动包

    这个JAR文件是Oracle JDBC驱动程序的一个版本,专为Java 6设计。"ojdbc6"这个名字中的"6"代表它支持Java SE 6。11.2.0.1.0是驱动的版本号,表明它对应于Oracle数据库11g Release 2的早期版本。这个驱动包包含了 ...

    oracle的jar包.rar

    例如,一个典型的Oracle JDBC连接字符串可能如下所示: ```java String url = "jdbc:oracle:thin:@//hostname:port/service_name"; ``` 在这个字符串中,`hostname`是Oracle数据库服务器的IP地址或域名,`port`是...

    com.oracle.ojdbc6-11.1.0.7.0

    是Oracle公司发布的JDBC驱动程序的一个特定版本,主要用于Java 6环境。然而,值得注意的是,该版本已经在官方渠道下架,意味着不再提供官方支持和更新,但依然可以在某些场景下使用。 1. **JDBC驱动概述**: JDBC...

    适用SQL Server 2016版本的数据库加载驱动包jdbc

    在IT领域,数据库管理和数据操作是至关重要的环节,而Java作为一种广泛应用的编程语言,与数据库交互时常常依赖于Java Database Connectivity(JDBC)接口。本文将深入探讨如何使用JDBC驱动包来连接SQL Server 2016...

    ojdbc14_src.zip数据库连接包反编译后的源码包

    ojdbc14是Oracle JDBC驱动的一个早期版本,它基于JDBC 3.0规范,适用于Java 1.4环境。 【描述】中的“帮助手懒得朋友们”暗示了这个源码包可能是为了方便开发者理解和调试Oracle数据库连接问题而提供的。通常,JDBC...

    解决oracle 驱动bug: preparestatement ArrayIndexOutOfBounds

    In Oracle Metalink (Oracle's support site - Note ID 736273.1) I found that this is a bug in JDBC adapter (version 10.2.0.0.0 to 11.1.0.7.0) that when you call preparedStatement with more than 7 ...

    Oracle驱动jar包和sqlserver驱动jar包

    - **classes12.jar**: 这是Oracle 9i版本的JDBC驱动程序,它包含了Oracle JDBC驱动的基本类和接口,使得Java应用程序可以连接到Oracle数据库。然而,由于已经过时,现在更推荐使用更新的驱动版本。 - **ojdbc14....

    oracl_ojdbc6

    ojdbc6.jar是Oracle JDBC驱动的一个特定版本,它支持Java SE 6环境,并包含了对JDBC 4.0规范的实现。这个版本的驱动提供了连接Oracle数据库、执行SQL语句、处理结果集等功能,同时也包含了Oracle特定的特性,如PL/...

Global site tag (gtag.js) - Google Analytics